Last active
March 24, 2021 07:02
-
-
Save debarko/161adfbad12c1ccd5301217ed05c17c7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################################ | |
# This gist is a solution of EECS 498-007 / 598-005 | |
# Deep Learning for Computer Vision Course | |
# Part 1 PyTorch 101 | |
# https://web.eecs.umich.edu/~justincj/teaching/eecs498/assignment1.html | |
# There can be multiple ways a problem can be solved | |
# and this doesn't guarantee that this is the best | |
# possible solution. Hence please feel free to optimise | |
# whereever possible. | |
# solutions by: debarko.de | |
################################################################################ | |
import torch | |
print(torch.__version__) | |
a = torch.tensor([1,2,3]) | |
a.cuda() | |
print("Here is a : ") | |
print(a) | |
print(type(a)) | |
print(a.dim()) | |
print(a.shape) | |
print(a[0]) | |
type(a[0]) | |
b=[[12,3,324],[1231,6787,345]] | |
b = torch.tensor(b) | |
print(b.dim()) | |
print(b.shape) | |
print(a[0].item()) | |
print(type(a[0].item())) | |
a[1]=1000 | |
print(a) | |
c = None | |
################################################################################ | |
# TODO: Construct a tensor c filled with all zeros, initializing from nested # | |
# Python lists. # | |
################################################################################ | |
# Replace "pass" statement with your code | |
c = torch.tensor([[0,0],[0,0],[0,0]]) | |
################################################################################ | |
# END OF YOUR CODE # | |
################################################################################ | |
print('c is a tensor: ', torch.is_tensor(c)) | |
print('Correct shape: ', c.shape == (3, 2)) | |
print('All zeros: ', (c == 0).all().item() == 1) | |
################################################################################ | |
# TODO: Set element (0, 1) of c to 10, and element (1, 0) of c to 100. # | |
################################################################################ | |
# Replace "pass" statement with your code | |
c[0,1]=10 | |
c[1,0]=100 | |
################################################################################ | |
# END OF YOUR CODE # | |
################################################################################ | |
print('\nAfter mutating:') | |
print('Correct shape: ', c.shape == (3, 2)) | |
print('c[0, 1] correct: ', c[0, 1] == 10) | |
print('c[1, 0] correct: ', c[1, 0] == 100) | |
print('Rest of c is still zero: ', (c == 0).sum().item() == 4) | |
a=torch.zeros(2,3) | |
print(a) | |
a=torch.zeros(3,2) | |
print(a) | |
b=torch.ones(1,2) | |
b | |
b=torch.ones(55,5) | |
b | |
c=torch.eye(10,9) | |
c | |
d=torch.rand(4,5) | |
print(d*200) | |
e = None | |
################################################################################ | |
# TODO: Create a tensor of shape (2, 3, 4) filled entirely with 7, stored in e # | |
################################################################################ | |
# Replace "pass" statement with your code | |
e=torch.full((2,3,4),int(7), out=None, dtype=int) | |
################################################################################ | |
# END OF YOUR CODE # | |
################################################################################ | |
print('e is a tensor:', torch.is_tensor(e)) | |
print('e has correct shape: ', e.shape == (2, 3, 4)) | |
print('e is filled with sevens: ', (e == 7).all().item() == 1) | |
# Let torch choose the datatype | |
x0 = torch.tensor([1, 2]) # List of integers | |
x1 = torch.tensor([1., 2.]) # List of floats | |
x2 = torch.tensor([1., 2]) # Mixed list | |
print('dtype when torch chooses for us:') | |
print('List of integers:', x0.dtype) | |
print('List of floats:', x1.dtype) | |
print('Mixed list:', x2.dtype) | |
# Force a particular datatype | |
y0 = torch.tensor([1, 2], dtype=torch.float32) # 32-bit float | |
y1 = torch.tensor([1, 2], dtype=torch.int32) # 32-bit (signed) integer | |
y2 = torch.tensor([1, 2], dtype=torch.int64) # 64-bit (signed) integer | |
print('\ndtype when we force a datatype:') | |
print('32-bit float: ', y0.dtype) | |
print('32-bit integer: ', y1.dtype) | |
print('64-bit integer: ', y2.dtype) | |
# Other creation ops also take a dtype argument | |
z0 = torch.ones(1, 2) # Let torch choose for us | |
z1 = torch.ones(1, 2, dtype=torch.int16) # 16-bit (signed) integer | |
z2 = torch.ones(1, 2, dtype=torch.uint8) # 8-bit (unsigned) integer | |
print('\ntorch.ones with different dtypes') | |
print('default dtype:', z0.dtype) | |
print('16-bit integer:', z1.dtype) | |
print('8-bit unsigned integer:', z2.dtype) | |
x0 = torch.eye(3, dtype=torch.int64) | |
x1 = x0.float() # Cast to 32-bit float | |
x2 = x0.long() # Cast to 64-bit float | |
x3 = x0.to(torch.float32) # Alternate way to cast to 32-bit float | |
x4 = x0.to(torch.float64) # Alternate way to cast to 64-bit float | |
print('x0:', x0.dtype) | |
print('x1:', x1.dtype) | |
print('x2:', x2.dtype) | |
print('x3:', x3.dtype) | |
print('x4:', x4.dtype) | |
print(x0) | |
print(x1) | |
print(x2) | |
print(x3) | |
print(x4) | |
x = None | |
############################################################################## | |
# TODO: Make x contain a six-element vector of 64-bit floating-bit values, # | |
# evenly spaced between 10 and 20. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
x=torch.linspace(10,20,6,dtype=torch.float64) | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('x is a tensor: ', torch.is_tensor(x)) | |
print('x has correct shape: ', x.shape == (6,)) | |
print('x has correct dtype: ', x.dtype == torch.float64) | |
y = [10, 12, 14, 16, 18, 20] | |
correct_vals = all(a.item() == b for a, b in zip(x, y)) | |
print('x has correct valus: ', correct_vals) | |
print(x) | |
a = torch.tensor([0, 11, 22, 33, 44, 55, 66]) | |
print(0, a) # (0) Original tensor | |
print(1, a[2:5]) # (1) Elements between index 2 and 5 | |
print(2, a[2:]) # (2) Elements after index 2 | |
print(3, a[:5]) # (3) Elements before index 5 | |
print(4, a[:]) # (4) All elements | |
print(5, a[1:5:2]) # (5) Every second element between indices 1 and 5 | |
print(6, a[:-1]) # (6) All but the last element | |
print(7, a[-4::2]) # (7) Every second element, starting from the fourth-last | |
# Create the following rank 2 tensor with shape (3, 4) | |
# [[ 1 2 3 4] | |
# [ 5 6 7 8] | |
# [ 9 10 11 12]] | |
a = torch.tensor([[1,2,3,4], [5,6,7,8], [9,10,11,12]]) | |
print('Original tensor:') | |
print(a) | |
print('shape: ', a.shape) | |
# Get row 1, and all columns. | |
print('\nSingle row:') | |
print(a[1, :]) | |
print(a[1]) # Gives the same result; we can omit : for trailing dimensions | |
print('shape: ', a[1].shape) | |
print('\nSingle column:') | |
print(a[:, 1]) | |
print('shape: ', a[:, 1].shape) | |
# Get the first two rows and the last three columns | |
print('\nFirst two rows, last two columns:') | |
print(a[:2, -3:]) | |
print('shape: ', a[:2, -3:].shape) | |
# Get every other row, and columns at index 1 and 2 | |
print('\nEvery other row, middle columns:') | |
print(a[::2, 1:3]) | |
print('shape: ', a[::2, 1:3].shape) | |
a = torch.tensor([[1,2,3,4], [5,6,7,8], [9,10,11,12]]) | |
print('Original tensor') | |
print(a) | |
row_r1 = a[1, :] # Rank 1 view of the second row of a | |
row_r2 = a[1:2, :] # Rank 2 view of the second row of a | |
print('\nTwo ways of accessing a single row:') | |
print(row_r1, row_r1.shape) | |
print(row_r2, row_r2.shape) | |
# We can make the same distinction when accessing columns:: | |
col_r1 = a[:, 1] | |
col_r2 = a[:, 1:2] | |
print('\nTwo ways of accessing a single column:') | |
print(col_r1, col_r1.shape) | |
print(col_r2, col_r2.shape) | |
row_r1 | |
row_r2 | |
# Create a tensor, a slice, and a clone of a slice | |
a = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]) | |
b = a[0, 1:] | |
c = a[0, 1:].clone() | |
print('Before mutating:') | |
print(a) | |
print(b) | |
print(c) | |
a[0, 1] = 20 # a[0, 1] and b[0] point to the same element | |
b[1] = 30 # b[1] and a[0, 2] point to the same element | |
c[2] = 40 # c is a clone, so it has its own data | |
print('\nAfter mutating:') | |
print(a) | |
print(b) | |
print(c) | |
print(a.storage().data_ptr() == c.storage().data_ptr()) | |
# We will use this helper function to check your results | |
def check(orig, actual, expected): | |
expected = torch.tensor(expected) | |
same_elements = (actual == expected).all().item() == 1 | |
same_storage = (orig.storage().data_ptr() == actual.storage().data_ptr()) | |
return same_elements and same_storage | |
# Create the following rank 2 tensor of shape (3, 5) | |
# [[ 1 2 3 4 5] | |
# [ 6 7 8 9 10] | |
# [11 12 13 14 15]] | |
a = torch.tensor([[1, 2, 3, 4, 5], [6, 7, 8, 8, 10], [11, 12, 13, 14, 15]]) | |
b, c, d, e = None, None, None, None | |
############################################################################## | |
# TODO: Extract the last row of a, and store it in b; it should have rank 1. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
b=a[2,:] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('b correct:', check(a, b, [11, 12, 13, 14, 15])) | |
############################################################################## | |
# TODO: Extract the third col of a, and store it in c; it should have rank 2 # | |
############################################################################## | |
# Replace "pass" statement with your code | |
c=a[:,2:3] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('c correct:', check(a, c, [[3], [8], [13]])) | |
############################################################################## | |
# TODO: Use slicing to extract the first two rows and first three columns # | |
# from a; store the result into d. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
d=a[0:2,0:3] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('d correct:', check(a, d, [[1, 2, 3], [6, 7, 8]])) | |
############################################################################## | |
# TODO: Use slicing to extract a subtensor of a consisting of rows 0 and 2 # | |
# and columns 1 and 4. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
e=a[0::2,1:5:3] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('e correct:', check(a, e, [[2, 5], [12, 15]])) | |
x = torch.zeros(4, 6, dtype=torch.int64) | |
############################################################################## | |
# TODO: Use slicing to modify the tensor x so it has the following contents: # | |
# [[1, 0, 2, 2, 2, 2], # | |
# [0, 1, 2, 2, 2, 2], # | |
# [3, 4, 3, 4, 5, 5], # | |
# [3, 4, 3, 4, 5, 5]] # | |
# This can be achieved using five slicing assignment operations. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
x[:2,2:]=torch.full((2,4),2,dtype=torch.int) | |
x[2:,4:]=torch.full((2,2),5,dtype=torch.int) | |
x[:2,:2]=torch.eye(2,2) | |
x[2:,:4]=torch.tensor([[3,4,3,4],[3,4,3,4]]) | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
expected = [ | |
[1, 0, 2, 2, 2, 2], | |
[0, 1, 2, 2, 2, 2], | |
[3, 4, 3, 4, 5, 5], | |
[3, 4, 3, 4, 5, 5], | |
] | |
print('correct:', x.tolist() == expected) | |
a = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) | |
print('Original tensor:') | |
print(a) | |
idx = [0, 0, 2, 1, 1] # index arrays can be Python lists of integers | |
print('\nReordered rows:') | |
print(a[idx]) | |
idx = torch.tensor([3, 2, 1, 0]) # Index arrays can be int64 torch tensors | |
print('\nReordered columns:') | |
print(a[:, idx]) | |
a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) | |
print('Original tensor:') | |
print(a) | |
idx = [0, 1, 2] | |
print('\nGet the diagonal:') | |
print(a[idx, idx]) | |
# Modify the diagonal | |
a[idx, idx] = torch.tensor([11, 22, 33]) | |
print('\nAfter setting the diagonal:') | |
print(a) | |
# Create a new tensor from which we will select elements | |
a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) | |
print('Original tensor:') | |
print(a) | |
# Take on element from each row of a: | |
# from row 0, take element 1; | |
# from row 1, take element 2; | |
# from row 2, take element 1; | |
# from row 3, take element 0 | |
idx0 = torch.arange(a.shape[0]) # Quick way to build [0, 1, 2, 3] | |
idx1 = torch.tensor([1, 2, 1, 0]) | |
print('\nSelect one element from each row:') | |
print(a[idx0, idx1]) | |
# Now set each of those elements to zero | |
a[idx0, idx1] = 0 | |
print('\nAfter modifying one element from each row:') | |
print(a) | |
# Build a tensor of shape (4, 3): | |
# [[ 1, 2, 3], | |
# [ 4, 5, 6], | |
# [ 7, 8, 9], | |
# [10, 11, 12]] | |
a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) | |
print('Here is a:') | |
print(a) | |
b, c, d = None, None, None | |
############################################################################## | |
# TODO: Use integer array indexing to create a tensor of shape (4, 4) where: # | |
# - The first two columns are the same as the first column of a # | |
# - The next column is the same as the third column of a # | |
# - The last column is the same as the second column of a # | |
# Store the resulting tensor in b. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
b=torch.zeros(a.shape[0], a.shape[0], dtype=torch.int64) | |
idx0 = [0,0,2,1] | |
b=a[:,idx0] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('\nHere is b:') | |
print(b) | |
expected = [[1, 1, 3, 2], [4, 4, 6, 5], [7, 7, 9, 8], [10, 10, 12, 11]] | |
print('b correct:', b.tolist() == expected) | |
############################################################################## | |
# TODO: Use integer array indexing to create a new tensor which is the same # | |
# as a, but has its rows reversed. Store the result in c. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
idx1 = [3,2,1,0] | |
c=a[idx1] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('\nHere is c:') | |
print(c) | |
expected = [[10, 11, 12], [7, 8, 9], [4, 5, 6], [1, 2, 3]] | |
print('c correct:', c.tolist() == expected) | |
############################################################################## | |
# TODO: Use integer array indexing to create a new tensor by selecting one # | |
# element from each column of a: # | |
# - From the first column, take the second element. # | |
# - From the second column, take the first element. # | |
# - From the third column, take the fourth element. # | |
# Store the result in d. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
idx2 = torch.arange(a.shape[1]) | |
idx3 = torch.tensor([1,0,3]) | |
d=a[idx3,idx2] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('\nHere is d:') | |
print(d) | |
expected = [4, 2, 12] | |
print('d correct:', d.tolist() == expected) | |
a = torch.tensor([[1,2], [3, 4], [5, 6]]) | |
print('Original tensor:') | |
print(a) | |
# Find the elements of a that are bigger than 3. The mask has the same shape as | |
# a, where each element of mask tells whether the corresponding element of a | |
# is greater than three. | |
mask = (a > 3) | |
print('\nMask tensor:') | |
print(mask) | |
# We can use the mask to construct a rank-1 tensor containing the elements of a | |
# that are selected by the mask | |
print('\nSelecting elements with the mask:') | |
print(a[mask]) | |
# We can also use boolean masks to modify tensors; for example this sets all | |
# elements <= 3 to zero: | |
a[a <= 3] = 0 | |
print('\nAfter modifying with a mask:') | |
print(a) | |
def num_negative(x): | |
""" | |
Return the number of negative values in the tensor x | |
Inputs: | |
- x: A tensor of any shape | |
Returns: | |
- num_neg: Number of negative values in x | |
""" | |
num_neg = 0 | |
############################################################################## | |
# TODO: Use boolean masks to count the number of negative elements in x. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
mask = x < 0 | |
num_neg=list(x[mask].shape)[0] | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
return num_neg | |
# Make a few test cases | |
torch.manual_seed(598) | |
x0 = torch.tensor([[-1, -1, 0], [0, 1, 2], [3, 4, 5]]) | |
x1 = torch.tensor([0, 1, 2, 3]) | |
x2 = torch.randn(100, 100) | |
assert num_negative(x0) == 2 | |
assert num_negative(x1) == 0 | |
assert num_negative(x2) == 4984 | |
print('num_negative seems to be correct!') | |
def make_one_hot(x): | |
""" | |
Construct a tensor of one-hot-vectors from a list of Python integers. | |
Input: | |
- x: A list of N ints | |
Returns: | |
- y: A tensor of shape (N, C) where C = 1 + max(x) is one more than the max | |
value in x. The nth row of y is a one-hot-vector representation of x[n]; | |
In other words, if x[n] = c then y[n, c] = 1; all other elements of y are | |
zeros. | |
""" | |
y = None | |
############################################################################## | |
# TODO: Complete the implementation of this function. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
max_val = 1+max(x) | |
dummy= torch.zeros(len(x), max_val, dtype=torch.int64) | |
idx0 = torch.arange(len(x)) | |
idx1 = torch.tensor(x) | |
dummy[idx0,idx1]=1 | |
y=dummy | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
return y | |
def check_one_hot(x, y): | |
C = y.shape[1] | |
for i, n in enumerate(x): | |
if n >= C: return False | |
for j in range(C): | |
expected = 1.0 if j == n else 0.0 | |
if y[i, j].item() != expected: return False | |
return True | |
x0 = [1, 4, 3, 2] | |
y0 = make_one_hot(x0) | |
print('Here is y0:') | |
print(y0) | |
assert check_one_hot(x0, y0), 'y0 is wrong' | |
x1 = [1, 3, 5, 7, 6, 2] | |
y1 = make_one_hot(x1) | |
print('\nHere is y1:') | |
print(y1) | |
assert check_one_hot(x1, y1), 'y1 is wrong' | |
print('all checks pass!') | |
x0 = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]) | |
print('Original tensor:') | |
print(x0) | |
print('shape:', x0.shape) | |
# Flatten x0 into a rank 1 vector of shape (8,) | |
x1 = x0.view(8) | |
print('\nFlattened tensor:') | |
print(x1) | |
print('shape:', x1.shape) | |
# Convert x1 to a rank 2 "row vector" of shape (1, 8) | |
x2 = x1.view(1, 8) | |
print('\nRow vector:') | |
print(x2) | |
print('shape:', x2.shape) | |
# Convert x1 to a rank 2 "column vector" of shape (8, 1) | |
x3 = x1.view(8, 1) | |
print('\nColumn vector:') | |
print(x3) | |
print('shape:', x3.shape) | |
# Convert x1 to a rank 3 tensor of shape (2, 2, 2): | |
x4 = x1.view(2, 2, 2) | |
print('\nRank 3 tensor:') | |
print(x4) | |
print('shape:', x4.shape) | |
# We can reuse these functions for tensors of different shapes | |
def flatten(x): | |
return x.view(-1) | |
def make_row_vec(x): | |
return x.view(1, -1) | |
x0 = torch.tensor([[1, 2, 3], [4, 5, 6]]) | |
x0_flat = flatten(x0) | |
x0_row = make_row_vec(x0) | |
print('x0:') | |
print(x0) | |
print('x0_flat:') | |
print(x0_flat) | |
print('x0_row:') | |
print(x0_row) | |
x1 = torch.tensor([[1, 2], [3, 4]]) | |
x1_flat = flatten(x1) | |
x1_row = make_row_vec(x1) | |
print('\nx1:') | |
print(x1) | |
print('x1_flat:') | |
print(x1_flat) | |
print('x1_row:') | |
print(x1_row) | |
x = torch.tensor([[1, 2, 3], [4, 5, 6]]) | |
x_flat = x.view(-1) | |
print('x before modifying:') | |
print(x) | |
print('x_flat before modifying:') | |
print(x_flat) | |
x[0, 0] = 10 # x[0, 0] and x_flat[0] point to the same data | |
x_flat[1] = 20 # x_flat[1] and x[0, 1] point to the same data | |
print('\nx after modifying:') | |
print(x) | |
print('x_flat after modifying:') | |
print(x_flat) | |
x = torch.tensor([[1, 2, 3], [4, 5, 6]]) | |
print('Original matrix:') | |
print(x) | |
print('\nTransposing with view DOES NOT WORK!') | |
print(x.view(3, 2)) | |
print('\nTransposed matrix:') | |
print(torch.t(x)) | |
print(x.t()) | |
# Create a tensor of shape (2, 3, 4) | |
x0 = torch.tensor([ | |
[[1, 2, 3, 4], | |
[5, 6, 7, 8], | |
[9, 10, 11, 12]], | |
[[13, 14, 15, 16], | |
[17, 18, 19, 20], | |
[21, 22, 23, 24]]]) | |
print('Original tensor:') | |
print(x0) | |
print('shape:', x0.shape) | |
# Swap axes 1 and 2; shape is (2, 4, 3) | |
x1 = x0.transpose(1, 2) | |
print('\nSwap axes 1 and 2:') | |
print(x1) | |
print(x1.shape) | |
# Permute axes; the argument (1, 2, 0) means: | |
# - Make the old dimension 1 appear at dimension 0; | |
# - Make the old dimension 2 appear at dimension 1; | |
# - Make the old dimension 0 appear at dimension 2 | |
# This results in a tensor of shape (3, 4, 2) | |
x2 = x0.permute(1, 2, 0) | |
print('\nPermute axes') | |
print(x2) | |
print('shape:', x2.shape) | |
x0 = torch.arange(24) | |
print('Here is x0:') | |
print(x0) | |
x1 = None | |
############################################################################## | |
# TODO: Use reshape operations to create x1 from x0 # | |
############################################################################## | |
# Review this line please, objective is to make x0 tensor | |
# in the shape of expected list below. | |
x1= x0.view(2,3,4).transpose(1,2).reshape(8,3).transpose(0,1) | |
# Please suggest any better way to do this tranposition | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('\nHere is x1:') | |
print(x1) | |
expected = [ | |
[0, 1, 2, 3, 12, 13, 14, 15], | |
[4, 5, 6, 7, 16, 17, 18, 19], | |
[8, 9, 10, 11, 20, 21, 22, 23]] | |
print('Correct:', x1.tolist() == expected) | |
x = torch.tensor([[1, 2, 3], | |
[4, 5, 6]], dtype=torch.float32) | |
print('Original tensor:') | |
print(x) | |
print('\nSum over entire tensor:') | |
print(torch.sum(x)) | |
print(x.sum()) | |
# We can sum over each row: | |
print('\nSum of each row:') | |
print(torch.sum(x, dim=0)) | |
print(x.sum(dim=0)) | |
# Sum over each column: | |
print('\nSum of each column:') | |
print(torch.sum(x, dim=1)) | |
print(x.sum(dim=1)) | |
x = torch.tensor([[2, 4, 3, 5], [3, 3, 5, 2]], dtype=torch.float32) | |
print('Original tensor:') | |
print(x, x.shape) | |
# Finding the overall minimum only returns a single value | |
print('\nOverall minimum: ', x.min()) | |
# Compute the minimum along each column; we get both the value and location: | |
# The minimum of the first column is 2, and it appears at index 0; | |
# the minimum of the second column is 3 and it appears at index 1; etc | |
col_min_vals, col_min_idxs = x.min(dim=0) | |
print('\nMinimum along each column:') | |
print('values:', col_min_vals) | |
print('idxs:', col_min_idxs) | |
print( x.min(dim=0)) | |
# Compute the minimum along each row; we get both the value and the minimum | |
row_min_vals, row_min_idxs = x.min(dim=1) | |
print('\nMinimum along each row:') | |
print('values:', row_min_vals) | |
print('idxs:', row_min_idxs) | |
# Create a tensor of shape (128, 10, 3, 64, 64) | |
x = torch.randn(2, 3, 3, 2, 3) | |
print(x) | |
# Take the mean over dimension 1; shape is now (128, 3, 64, 64) | |
x = x.mean(dim=1) | |
print(x) | |
# Take the sum over dimension 2; shape is now (128, 3, 64) | |
x = x.sum(dim=2) | |
print(x) | |
# Take the mean over dimension 1, but keep the dimension from being eliminated | |
# by passing keepdim=True; shape is now (128, 1, 64) | |
x = x.mean(dim=1, keepdim=True) | |
print(x) | |
def zero_row_min(x): | |
""" | |
Return a copy of x, where the minimum value along each row has been set to 0. | |
For example, if x is: | |
x = torch.tensor([[ | |
[10, 20, 30], | |
[ 2, 5, 1] | |
]]) | |
Then y = zero_row_min(x) should be: | |
torch.tensor([ | |
[0, 20, 30], | |
[2, 5, 0] | |
]) | |
Inputs: | |
- x: Tensor of rank 2 with shape (N, M) | |
Returns: | |
- y: Tensor of rank 2 that is a copy of x, except the minimum value along each | |
row is replaced with 0. | |
""" | |
y = x.clone() | |
############################################################################## | |
# TODO: Complete the implementation of this function. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
row_min_vals, row_min_idxs = x.min(dim=1) | |
row_min_idxs = row_min_idxs.tolist() | |
for i in range(len(row_min_idxs)): | |
y[i][row_min_idxs[i]]=0 | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
return y | |
x0 = torch.tensor([[10, 20, 30], [2, 5, 1]]) | |
print('Here is x0:') | |
print(x0) | |
y0 = zero_row_min(x0) | |
print('Here is y0:') | |
print(y0) | |
assert y0.tolist() == [[0, 20, 30], [2, 5, 0]] | |
x1 = torch.tensor([[2, 5, 10, -1], [1, 3, 2, 4], [5, 6, 2, 10]]) | |
print('\nHere is x1:') | |
print(x1) | |
y1 = zero_row_min(x1) | |
print('Here is y1:') | |
print(y1) | |
assert y1.tolist() == [[2, 5, 10, 0], [0, 3, 2, 4], [5, 6, 0, 10]] | |
print('\nSimple tests pass!') | |
v = torch.tensor([9,10], dtype=torch.float32) | |
w = torch.tensor([11, 12], dtype=torch.float32) | |
# Inner product of vectors | |
print('Dot products:') | |
print(torch.dot(v, w)) | |
print(v.dot(w)) | |
# dot only works for vectors -- it will give an error for tensors of rank > 1 | |
x = torch.tensor([[1,2],[3,4]], dtype=torch.float32) | |
y = torch.tensor([[5,6],[7,8]], dtype=torch.float32) | |
print(x) | |
print(y) | |
try: | |
print(x.dot(y)) | |
except RuntimeError as e: | |
print(e) | |
# Instead we use mm for matrix-matrix products: | |
print('\nMatrix-matrix product:') | |
print(torch.mm(x, y)) | |
print(x.mm(y)) | |
B, N, M, P = 3, 2, 5, 4 | |
x = torch.rand(B, N, M) # Random tensor of shape (B, N, M) | |
y = torch.rand(B, M, P) # Random tensor of shape (B, M, P) | |
# We can use a for loop to (inefficiently) compute a batch of matrix multiply | |
# operations | |
z1 = torch.empty(B, N, P) # Empty tensor of shape (B, N, P) | |
for i in range(B): | |
z1[i] = x[i].mm(y[i]) | |
print('Here is the result of batched matrix multiply with a loop:') | |
print(z1) | |
z2 = None | |
############################################################################## | |
# TODO: Use bmm to compute a batched matrix multiply between x and y; store # | |
# the result in z2. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
z2=torch.bmm(x,y) | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
print('\nHere is the result of batched matrix multiply with bmm:') | |
print(z2) | |
# The two may not return exactly the same result; different linear algebra | |
# routines often return slightly different results due to the fact that | |
# floating-point math is non-exact and non-associative. | |
diff = (z1 - z2).abs().max().item() | |
print('\nDifference:', diff) | |
print('Difference within threshold:', diff < 1e-6) | |
def normalize_columns(x): | |
""" | |
Normalize the columns of a matrix by subtracting the mean and dividing by the | |
standard deviation. | |
Inputs: | |
- x: Tensor of shape (N, M) | |
Returns: | |
- y: Tensor of shape (N, M) which is a copy of x with normalized columns. | |
""" | |
y = x.clone() | |
############################################################################## | |
# TODO: Complete the implementation of this function. Do not modify x. # | |
# Your implementation should not use any loops; instead you should use # | |
# reduction and broadcasting operations. # | |
############################################################################## | |
# Replace "pass" statement with your code | |
print(x) | |
meanT = torch.mean(y,dim=0) | |
stdT = torch.std(y,dim=0) | |
print('meanT ',meanT) | |
print('stdT ',stdT) | |
y = (y - meanT) / stdT | |
print('y ',y) | |
print('expected\n',torch.tensor([[0., 1., 1.], [1., -1., -1.], [-1., 0., 0.]])) | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
return y | |
x0 = torch.tensor([[0., 30., 600.], [1., 10., 200.], [-1., 20., 400.]]) | |
y0 = normalize_columns(x0) | |
print('Here is x0:') | |
print(x0) | |
print('Here is y0:') | |
print(y0) | |
assert y0.tolist() == [[0., 1., 1.], [1., -1., -1.], [-1., 0., 0.]] | |
assert x0.tolist() == [[0., 30., 600.], [1., 10., 200.], [-1., 20., 400.]] | |
p=torch.tensor([[30.,10.,20.]]) | |
print(torch.std(p)) | |
print(torch.mean(p)) | |
if torch.cuda.is_available: | |
print('PyTorch can use GPUs!') | |
else: | |
print('PyTorch cannot use GPUs.') | |
import time | |
a_cpu = torch.randn(10000, 10000, dtype=torch.float32) | |
b_cpu = torch.randn(10000, 10000, dtype=torch.float32) | |
a_gpu = a_cpu.cuda() | |
b_gpu = b_cpu.cuda() | |
torch.cuda.synchronize() | |
t0 = time.time() | |
c_cpu = a_cpu + b_cpu | |
t1 = time.time() | |
c_gpu = a_gpu + b_gpu | |
torch.cuda.synchronize() | |
t2 = time.time() | |
# Check that they computed the same thing | |
diff = (c_gpu.cpu() - c_cpu).abs().max().item() | |
print('Max difference between c_gpu and c_cpu:', diff) | |
cpu_time = 1000.0 * (t1 - t0) | |
gpu_time = 1000.0 * (t2 - t1) | |
print('CPU time: %.2f ms' % cpu_time) | |
print('GPU time: %.2f ms' % gpu_time) | |
print('GPU speedup: %.2f x' % (cpu_time / gpu_time)) | |
import time | |
x = torch.rand(512, 4096) | |
w = torch.rand(4096, 4096) | |
t0 = time.time() | |
y0 = x.mm(w) | |
t1 = time.time() | |
y1 = None | |
############################################################################## | |
# TODO: Write a bit of code that performs matrix multiplication of x and w # | |
# on the GPU, and then moves the result back to the CPU. Store the result # | |
# in y1. | |
############################################################################## | |
# Replace "pass" statement with your code | |
x = x.cuda() | |
w = w.cuda() | |
y = torch.matmul(x,w) | |
y1 = y.cpu() | |
############################################################################## | |
# END OF YOUR CODE # | |
############################################################################## | |
torch.cuda.synchronize() | |
t2 = time.time() | |
print('y1 on CPU:', y1.device == torch.device('cpu')) | |
diff = (y0 - y1).abs().max().item() | |
print('Max difference between y0 and y1:', diff) | |
print('Difference within tolerance:', diff < 5e-2) | |
cpu_time = 1000.0 * (t1 - t0) | |
gpu_time = 1000.0 * (t2 - t1) | |
print('CPU time: %.2f ms' % cpu_time) | |
print('GPU time: %.2f ms' % gpu_time) | |
print('GPU speedup: %.2f x' % (cpu_time / gpu_time)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment