<jupyter_start><jupyter_text>Set up<jupyter_code>import numpy as np
import torch
SEED = 1234
# set seed for reproducibility
np.random.seed(seed=SEED)
torch.manual_seed(SEED)<jupyter_output><empty_output><jupyter_text>Basics<jupyter_code># Creating a random tensor
x = torch.randn(2, 3) # normal distribution (rand(2,3) -> uniform distribution)
print(f"Type: {x.type()}")
print(f"Size: {x.shape}")
print(f"Values: \n{x}")
# Zero and Ones tensor
x = torch.zeros(2, 3)
print (x)
x = torch.ones(2, 3)
print (x)
# List → Tensor
x = torch.Tensor([[1, 2, 3],[4, 5, 6]])
print(f"Size: {x.shape}")
print(f"Values: \n{x}")
# NumPy array → Tensor
x = torch.Tensor(np.random.rand(2, 3))
print(f"Size: {x.shape}")
print(f"Values: \n{x}")
# Changing tensor type
x = torch.Tensor(3, 4)
print(f"Type: {x.type()}")
x = x.long()
print(f"Type: {x.type()}")<jupyter_output>Type: torch.FloatTensor
Type: torch.LongTensor<jupyter_text>Operations<jupyter_code># Addition
x = torch.randn(2, 3)
y = torch.randn(2, 3)
z = x + y
print(f"Size: {z.shape}")
print(f"Values: \n{z}")
# Dot product
x = torch.randn(2, 3)
print(f"Size: {x.shape}")
print(f"Values: \n{x}")
y = torch.randn(3, 2)
print(f"Size: {y.shape}")
print(f"Values: \n{y}")
z = torch.mm(x, y)
print(f"Size: {z.shape}")
print(f"Values: \n{z}")
# Transpose
x = torch.randn(2, 3)
print(f"Size: {x.shape}")
print(f"Values: \n{x}")
y = torch.t(x)
print(f"Size: {y.shape}")
print(f"Values: \n{y}")
# Reshape
x = torch.randn(2, 3)
z = x.view(3, 2)
print(f"Size: {z.shape}")
print(f"Values: \n{z}")
# Dangers of reshaping (unintended consequences)
x = torch.tensor([
    [[1,1,1,1], [2,2,2,2], [3,3,3,3]],
    [[10,10,10,10], [20,20,20,20], [30,30,30,30]]
])
print(f"Size: {x.shape}")
print(f"x: \n{x}\n")

a = x.view(x.size(1), -1)
print(f"\nSize: {a.shape}")
print(f"a: \n{a}\n")

b = x.transpose(0,1).contiguous()
print(f"\nSize: {b.shape}")
print(f"b: \n{b}\n")

c = b.view(b.size(0), -1)
print(f"\nSize: {c.shape}")
print(f"c: \n{c}")
# Dimensional operations
x = torch.randn(2, 3)
print(f"Values: \n{x}")
y = torch.sum(x, dim=0) # add each row's value for every column
print(f"Values: \n{y}")
z = torch.sum(x, dim=1) # add each columns's value for every row
print(f"Values: \n{z}")<jupyter_output>Values: 
tensor([[ 0.5797, -0.0599,  0.1816],
        [-0.6797, -0.2567, -1.8189]])
Values: 
tensor([-0.1000, -0.3166, -1.6373])
Values: 
tensor([ 0.7013, -2.7553])<jupyter_text>Indexing<jupyter_code>x = torch.randn(3, 4)
print (f"x: \n{x}")
print (f"x[:1]: \n{x[:1]}")
print (f"x[:1, 1:3]: \n{x[:1, 1:3]}")<jupyter_output>x: 
tensor([[ 0.2111,  0.3372,  0.6638,  1.0397],
        [ 1.8434,  0.6588, -0.2349, -0.0306],
        [ 1.7462, -0.0722, -1.6794, -1.7010]])
x[:1]: 
tensor([[0.2111, 0.3372, 0.6638, 1.0397]])
x[:1, 1:3]: 
tensor([[0.3372, 0.6638]])<jupyter_text>Slicing<jupyter_code># Select with dimensional indicies
x = torch.randn(2, 3)
print(f"Values: \n{x}")

col_indices = torch.LongTensor([0, 2])
chosen = torch.index_select(x, dim=1, index=col_indices) # values from column 0 & 2
print(f"Values: \n{chosen}")

row_indices = torch.LongTensor([0, 1])
col_indices = torch.LongTensor([0, 2])
chosen = x[row_indices, col_indices] # values from (0, 0) & (1, 2)
print(f"Values: \n{chosen}")<jupyter_output>Values: 
tensor([[ 0.6486,  1.7653,  1.0812],
        [ 1.2436,  0.8971, -0.0784]])
Values: 
tensor([[ 0.6486,  1.0812],
        [ 1.2436, -0.0784]])
Values: 
tensor([ 0.6486, -0.0784])<jupyter_text>JoiningJoining<jupyter_code># Row Concatenation
x = torch.randn(2, 3)
print(f"Values: \n{x}")

y = torch.cat([x, x], dim=0) # stack by rows (dim=1 to stack by columns)
print(f"Values: \n{y}")
# Column Concatenation
x = torch.randn(2, 3)
print(f"Values: \n{x}")

y = torch.cat([x, x], dim=1) # stack by columns (dim=0 to stack by rows)
print(f"Values: \n{y}")<jupyter_output>Values: 
tensor([[ 0.8246, -0.5723, -0.4876],
        [ 0.1944, -1.0481, -0.0741]])
Values: 
tensor([[ 0.8246, -0.5723, -0.4876,  0.8246, -0.5723, -0.4876],
        [ 0.1944, -1.0481, -0.0741,  0.1944, -1.0481, -0.0741]])<jupyter_text>Gradients<jupyter_code># Tensors with gradient bookkeeping
x = torch.rand(3,4, requires_grad=True)
y = 3*x + 2
z = y.mean()
z.backward() # z has to be scalar
print(f"x: \n{x}")
print(f"x.grad: \n{x.grad}")<jupyter_output>x: 
tensor([[0.5894, 0.5872, 0.9643, 0.7768],
        [0.8447, 0.7195, 0.7101, 0.4130],
        [0.0587, 0.0776, 0.1886, 0.1763]], requires_grad=True)
x.grad: 
tensor([[0.2500, 0.2500, 0.2500, 0.2500],
        [0.2500, 0.2500, 0.2500, 0.2500],
        [0.2500, 0.2500, 0.2500, 0.2500]])<jupyter_text>CUDA<jupyter_code># Is CUDA available
print(torch.cuda.is_available())
# import dependencies
import torch
# Is CUDA available  ow?
print(torch.cuda.is_available())
# set device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print("Device: ", device)
# compute with cuda device
x = torch.rand(2,3)
print(f"x.is_cuda: {x.is_cuda}")
x = torch.rand(2,3).to(device) # sTensor is stored on the GPU
print(f"x.is_cuda: {x.is_cuda}")<jupyter_output>x.is_cuda: False
x.is_cuda: True
{'fraction_non_alphanumeric': 0.22859960552268244, 'fraction_numerical': 0.10690335305719921, 'mean_word_length': 4.536026200873362, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '638646', 'license': 'MIT', 'n_tokens_mistral': 2640, 'n_tokens_neox': 2414, 'n_words': 478, 'path': 'PyTorch_Fundamentals.ipynb', 'repo_name': 'callezenwaka/machine-learning', 'size': '5070'}