eaglelandsonce commited on
Commit
701b403
·
verified ·
1 Parent(s): 88f9cbf

Delete pages/21_Intro2Tensors.py

Browse files
Files changed (1) hide show
  1. pages/21_Intro2Tensors.py +0 -380
pages/21_Intro2Tensors.py DELETED
@@ -1,380 +0,0 @@
1
- import streamlit as st
2
- import torch
3
- import io
4
- import sys
5
-
6
- # Function to execute the input code and capture print statements
7
- def execute_code(code):
8
- # Redirect stdout to capture print statements
9
- old_stdout = sys.stdout
10
- sys.stdout = mystdout = io.StringIO()
11
-
12
- global_vars = {"torch": torch}
13
- local_vars = {}
14
- try:
15
- exec(code, global_vars, local_vars)
16
- output = mystdout.getvalue()
17
- except Exception as e:
18
- output = str(e)
19
- finally:
20
- # Reset redirect.
21
- sys.stdout = old_stdout
22
-
23
- return output, local_vars
24
-
25
- # Dictionary with exercise details
26
- exercises = {
27
- "Exercise 1: Create and Manipulate Tensors": {
28
- "description": "Tensors are the core data structure in PyTorch, similar to arrays in NumPy but with additional capabilities for GPU acceleration. This exercise introduces how to create tensors from various data sources such as lists and NumPy arrays. It also covers basic tensor operations like addition, subtraction, and element-wise multiplication, which are fundamental for manipulating data in PyTorch.",
29
- "code": '''import torch
30
- import numpy as np
31
-
32
- # Creating tensors from Python lists
33
- # This creates a 1D tensor from the list [1, 2, 3]
34
- tensor_from_list = torch.tensor([1, 2, 3])
35
- print("Tensor from list:", tensor_from_list)
36
-
37
- # Creating tensors from NumPy arrays
38
- # This converts a NumPy array to a tensor
39
- numpy_array = np.array([4, 5, 6])
40
- tensor_from_numpy = torch.tensor(numpy_array)
41
- print("Tensor from NumPy array:", tensor_from_numpy)
42
-
43
- # Performing basic tensor operations
44
- tensor1 = torch.tensor([1, 2, 3])
45
- tensor2 = torch.tensor([4, 5, 6])
46
-
47
- # Addition
48
- addition = tensor1 + tensor2
49
- print("Addition:", addition)
50
-
51
- # Subtraction
52
- subtraction = tensor1 - tensor2
53
- print("Subtraction:", subtraction)
54
-
55
- # Element-wise multiplication
56
- elementwise_multiplication = tensor1 * tensor2
57
- print("Element-wise Multiplication:", elementwise_multiplication)
58
- '''
59
- },
60
- "Exercise 2: Tensor Indexing and Slicing": {
61
- "description": "Indexing and slicing allow you to access and manipulate specific elements and sub-tensors. This is crucial for tasks such as data preprocessing and manipulation in machine learning workflows. This exercise demonstrates how to index and slice tensors to extract and modify elements efficiently.",
62
- "code": '''import torch
63
-
64
- # Creating a 2D tensor (matrix)
65
- tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
66
-
67
- # Indexing elements
68
- # Accessing the element at the 2nd row and 3rd column (indexing starts at 0)
69
- element = tensor[1, 2]
70
- print("Element at index [1, 2]:", element)
71
-
72
- # Slicing sub-tensors
73
- # Extracting the entire second row
74
- row = tensor[1, :]
75
- print("Second row:", row)
76
-
77
- # Extracting the entire third column
78
- column = tensor[:, 2]
79
- print("Third column:", column)
80
-
81
- # Modifying elements
82
- # Changing the first element of the tensor to 10
83
- tensor[0, 0] = 10
84
- print("Modified tensor:", tensor)
85
- '''
86
- },
87
- "Exercise 3: Tensor Reshaping and Transposing": {
88
- "description": "Reshaping and transposing tensors are common operations when preparing data for neural networks. Reshaping allows you to change the layout of tensor data without altering its data. Transposing changes the orientation of the data, which is useful for operations like matrix multiplication. This exercise covers reshaping using `view()` and `reshape()`, and transposing using `transpose()` and `permute()`.",
89
- "code": '''import torch
90
-
91
- # Creating a 2D tensor
92
- tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
93
-
94
- # Reshaping the tensor
95
- # Changing the shape of the tensor to (3, 2)
96
- reshaped_tensor = tensor.view(3, 2)
97
- print("Reshaped tensor:", reshaped_tensor)
98
-
99
- # Another way to reshape using reshape()
100
- reshaped_tensor2 = tensor.reshape(-1) # Flattening the tensor
101
- print("Reshaped tensor (flattened):", reshaped_tensor2)
102
-
103
- # Transposing the tensor
104
- # Swapping the dimensions of the tensor (transpose rows and columns)
105
- transposed_tensor = tensor.t()
106
- print("Transposed tensor:", transposed_tensor)
107
-
108
- # Using permute for higher-dimensional tensors
109
- tensor_3d = torch.randn(2, 3, 4) # Creating a random 3D tensor
110
- # Permuting dimensions
111
- permuted_tensor = tensor_3d.permute(2, 0, 1)
112
- print("Permuted tensor shape:", permuted_tensor.shape)
113
- '''
114
- },
115
- "Exercise 4: Tensor Operations and Broadcasting": {
116
- "description": "Broadcasting in PyTorch allows you to perform arithmetic operations on tensors of different shapes. This can simplify code and reduce the need for explicit reshaping. This exercise demonstrates matrix multiplication, the concept of broadcasting, and the application of element-wise functions like sine and exponential.",
117
- "code": '''import torch
118
-
119
- # Matrix multiplication
120
- tensor1 = torch.tensor([[1, 2], [3, 4]])
121
- tensor2 = torch.tensor([[5, 6], [7, 8]])
122
-
123
- # Performing matrix multiplication using matmul
124
- matmul_result = torch.matmul(tensor1, tensor2)
125
- print("Matrix multiplication result:", matmul_result)
126
-
127
- # Broadcasting example
128
- # Broadcasting allows tensor3 and tensor4 to be added despite their different shapes
129
- tensor3 = torch.tensor([1, 2, 3])
130
- tensor4 = torch.tensor([[1], [2], [3]])
131
- broadcast_result = tensor3 + tensor4
132
- print("Broadcasting result:", broadcast_result)
133
-
134
- # Element-wise functions
135
- # Applying sine function element-wise
136
- sin_result = torch.sin(tensor3)
137
- print("Sine of tensor3:", sin_result)
138
-
139
- # Applying exponential function element-wise
140
- exp_result = torch.exp(tensor3)
141
- print("Exponential of tensor3:", exp_result)
142
-
143
- # Applying square root function element-wise
144
- # Note: sqrt requires the tensor to be of floating-point type
145
- sqrt_result = torch.sqrt(tensor3.float())
146
- print("Square root of tensor3:", sqrt_result)
147
- '''
148
- },
149
- "Exercise 5: Tensor Initialization": {
150
- "description": "Proper initialization of tensors is crucial for neural network training and other machine learning tasks. This exercise explores various methods to initialize tensors, such as filling them with zeros, ones, random values, and specific distributions. Understanding these methods helps in setting up model parameters and test data.",
151
- "code": '''import torch
152
-
153
- # Creating tensors filled with zeros and ones
154
- zeros_tensor = torch.zeros(3, 3)
155
- print("Zeros tensor:", zeros_tensor)
156
-
157
- ones_tensor = torch.ones(3, 3)
158
- print("Ones tensor:", ones_tensor)
159
-
160
- # Randomly initialized tensors
161
- # Uniform distribution in the range [0, 1)
162
- rand_tensor = torch.rand(3, 3)
163
- print("Uniform random tensor:", rand_tensor)
164
-
165
- # Normal distribution with mean 0 and variance 1
166
- randn_tensor = torch.randn(3, 3)
167
- print("Normal random tensor:", randn_tensor)
168
-
169
- # Random integers in the range [0, 10)
170
- randint_tensor = torch.randint(0, 10, (3, 3))
171
- print("Random integer tensor:", randint_tensor)
172
-
173
- # Initializing tensors with specific distributions
174
- # Normal distribution with custom mean and standard deviation
175
- normal_tensor = torch.normal(mean=0, std=1, size=(3, 3))
176
- print("Normal distribution tensor:", normal_tensor)
177
-
178
- # Uniform distribution in a custom range [0, 1)
179
- uniform_tensor = torch.empty(3, 3).uniform_(0, 1)
180
- print("Uniform distribution tensor:", uniform_tensor)
181
- '''
182
- },
183
- "Exercise 6: Tensor Arithmetic Operations": {
184
- "description": "Arithmetic operations on tensors are essential for numerous tasks in machine learning, including data preprocessing and neural network computations. This exercise covers basic arithmetic with tensors, in-place operations, and aggregation functions that compute summaries over tensor elements.",
185
- "code": '''import torch
186
-
187
- # Creating a 1D tensor
188
- tensor = torch.tensor([1.0, 2.0, 3.0])
189
-
190
- # Scalar-tensor operations
191
- # Adding a scalar to each element of the tensor
192
- add_scalar = tensor + 5
193
- print("Addition with scalar:", add_scalar)
194
-
195
- # Multiplying each element by a scalar
196
- mul_scalar = tensor * 2
197
- print("Multiplication with scalar:", mul_scalar)
198
-
199
- # In-place operations (modify the original tensor)
200
- # Adding 5 to each element of the tensor
201
- tensor.add_(5)
202
- print("In-place addition:", tensor)
203
-
204
- # Tensor aggregation operations
205
- tensor = torch.tensor([[1, 2], [3, 4]])
206
-
207
- # Summing all elements
208
- sum_all = tensor.sum()
209
- print("Sum of all elements:", sum_all)
210
-
211
- # Computing the mean of all elements
212
- mean_all = tensor.mean()
213
- print("Mean of all elements:", mean_all)
214
-
215
- # Finding the maximum element
216
- max_all = tensor.max()
217
- print("Maximum element:", max_all)
218
- '''
219
- },
220
- "Exercise 7: Tensor Comparison and Logical Operations": {
221
- "description": "Comparison and logical operations enable you to make conditional selections and perform logical checks on tensors. This is crucial for tasks such as filtering data and implementing decision-based logic in machine learning workflows. This exercise demonstrates the use of comparison operators and logical functions, which are often used in neural network training and data analysis.",
222
- "code": '''import torch
223
-
224
- # Creating two tensors for comparison
225
- tensor1 = torch.tensor([1, 2, 3])
226
- tensor2 = torch.tensor([3, 2, 1])
227
-
228
- # Comparison operations
229
- # Checking if elements in tensor1 are greater than corresponding elements in tensor2
230
- greater_than = tensor1 > tensor2
231
- print("Greater than comparison:", greater_than)
232
-
233
- # Checking if elements in tensor1 are equal to corresponding elements in tensor2
234
- equal = tensor1 == tensor2
235
- print("Equality comparison:", equal)
236
-
237
- # Logical operations
238
- # Logical AND operation between comparison results
239
- logical_and = torch.logical_and(tensor1 > 1, tensor2 < 3)
240
- print("Logical AND:", logical_and)
241
-
242
- # Logical OR operation between comparison results
243
- logical_or = torch.logical_or(tensor1 < 3, tensor2 > 1)
244
- print("Logical OR:", logical_or)
245
-
246
- # Logical NOT operation
247
- logical_not = torch.logical_not(tensor1 < 3)
248
- print("Logical NOT:", logical_not)
249
-
250
- # Conditional selection using torch.where
251
- # Selecting elements from tensor1 if condition is True, otherwise from tensor2
252
- selected_tensor = torch.where(tensor1 > 2, tensor1, tensor2)
253
- print("Conditional selection:", selected_tensor)
254
- '''
255
- },
256
- "Exercise 8: Tensor Reduction Operations": {
257
- "description": "Reduction operations aggregate tensor elements along specified dimensions, providing summarized results like sums, means, and indices of maximum or minimum values. This exercise covers essential reduction operations, which are commonly used in loss functions and performance metrics in machine learning.",
258
- "code": '''import torch
259
-
260
- # Creating a 2D tensor (matrix)
261
- tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
262
-
263
- # Reduction operations along dimensions
264
- # Summing elements along dimension 0 (rows)
265
- sum_dim0 = tensor.sum(dim=0)
266
- print("Sum along dimension 0:", sum_dim0)
267
-
268
- # Computing the mean along dimension 1 (columns)
269
- mean_dim1 = tensor.mean(dim=1)
270
- print("Mean along dimension 1:", mean_dim1)
271
-
272
- # Computing the product of all elements in the tensor
273
- prod_all = tensor.prod()
274
- print("Product of all elements:", prod_all)
275
-
276
- # Advanced reduction operations
277
- # Finding the index of the maximum element in the flattened tensor
278
- argmax_all = tensor.argmax()
279
- print("Index of maximum element:", argmax_all)
280
-
281
- # Finding the indices of the minimum elements along dimension 0
282
- argmin_dim0 = tensor.argmin(dim=0)
283
- print("Indices of minimum elements along dimension 0:", argmin_dim0)
284
- '''
285
- },
286
- "Exercise 9: Tensor Cloning and Detachment": {
287
- "description": "Cloning and detaching tensors are important when working with gradients in neural networks. Cloning creates a copy of a tensor, while detaching removes it from the computation graph to prevent gradient tracking. This exercise demonstrates these operations, which are crucial for managing tensor operations in complex neural networks.",
288
- "code": '''import torch
289
-
290
- # Creating a tensor with gradient tracking enabled
291
- tensor = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
292
-
293
- # Cloning the tensor
294
- # This creates a new tensor with the same data but no gradient history
295
- cloned_tensor = tensor.clone()
296
- print("Original tensor:", tensor)
297
- print("Cloned tensor:", cloned_tensor)
298
-
299
- # Detaching the tensor from the computation graph
300
- # This removes the tensor from the gradient computation graph
301
- detached_tensor = tensor.detach()
302
- print("Detached tensor:", detached_tensor)
303
-
304
- # Comparing original and detached tensors
305
- # Modifying the original tensor (note that in-place operations modify the tensor in place)
306
- tensor.add_(1)
307
- print("Modified original tensor:", tensor)
308
- print("Detached tensor remains unchanged:", detached_tensor)
309
- '''
310
- },
311
- "Exercise 10: GPU Operations with Tensors": {
312
- "description": "Utilizing GPUs can significantly speed up tensor operations, which is crucial for training large neural networks. This exercise covers checking for GPU availability, moving tensors to GPU, and performing operations on GPU to compare performance with CPU operations.",
313
- "code": '''import torch
314
- import time
315
-
316
- # Check for GPU availability
317
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
318
- print("Using device:", device)
319
-
320
- # Creating a tensor and moving it to GPU if available
321
- tensor = torch.tensor([1.0, 2.0, 3.0])
322
- tensor = tensor.to(device)
323
- print("Tensor on GPU:", tensor)
324
-
325
- # Perform operations on GPU
326
- # Adding a scalar to each element of the tensor on GPU
327
- tensor_add = tensor + 5
328
- print("Tensor after addition on GPU:", tensor_add)
329
-
330
- # Compare speed of operations on CPU vs GPU
331
- # Creating a large tensor for performance comparison
332
- cpu_tensor = torch.randn(10000, 10000)
333
-
334
- # CPU operation
335
- start_time = time.time()
336
- cpu_result = cpu_tensor @ cpu_tensor.T # Matrix multiplication
337
- end_time = time.time()
338
- print("CPU operation time:", end_time - start_time, "seconds")
339
-
340
- # GPU operation (if available)
341
- if torch.cuda.is_available():
342
- gpu_tensor = cpu_tensor.to(device)
343
- start_time = time.time()
344
- gpu_result = gpu_tensor @ gpu_tensor.T # Matrix multiplication
345
- torch.cuda.synchronize() # Wait for GPU operation to finish
346
- end_time = time.time()
347
- print("GPU operation time:", end_time - start_time, "seconds")
348
- '''
349
- }
350
- }
351
-
352
- st.title('PyTorch Code Runner')
353
-
354
- # Side menu for exercises
355
- exercise_choice = st.sidebar.radio("Choose an exercise", list(exercises.keys()))
356
-
357
- # Display the chosen exercise description
358
- st.subheader(exercise_choice)
359
- st.write(exercises[exercise_choice]["description"])
360
-
361
- # Text area for inputting the PyTorch code
362
- code_input = st.text_area("Enter your PyTorch code here", height=300, value=exercises[exercise_choice]["code"])
363
-
364
- # Button to execute the code
365
- if st.button("Run Code"):
366
- # Prepend the import statement
367
- code_to_run = "import torch\n" + code_input
368
-
369
- # Execute the code and capture the output
370
- output, variables = execute_code(code_to_run)
371
-
372
- # Display the output
373
- st.subheader('Output')
374
- st.text(output)
375
-
376
- # Display returned variables
377
- if variables:
378
- st.subheader('Variables')
379
- for key, value in variables.items():
380
- st.text(f"{key}: {value}")