import numpy as np
import torch
30 PyTorch
30.1 Linear Regression
An introduction to using tensors and gradients
30.1.1 Synthetic Data
= np.random.randn(200, 2).astype('float32') x
Note y
is a column vector
= np.array([12 - 0.8 * x[:, 0] + 1.2 * x[:, 1]], dtype='float32').T y
= torch.as_tensor(x)
x x.shape
torch.Size([200, 2])
= torch.as_tensor(y)
y y.shape
torch.Size([200, 1])
30.1.2 Init bias and weights
= torch.tensor(0., requires_grad=True) b
= torch.randn(2, 1, requires_grad=True) w
30.1.3 Train
def model(x):
return x @ w.t() + b
def mse(t1, t2):
= t1 - t2
diff return torch.sum(diff * diff) / diff.numel()
= 0.5
lr = 100 niter
for i in range(niter):
= b + torch.mm(x, w)
y_hat = torch.mean(torch.pow(y - y_hat, 2))
loss
loss.backward()
with torch.no_grad():
-= w.grad * lr
w -= b.grad * lr
b
w.grad.zero_() b.grad.zero_()
print(w)
tensor([[-0.8000],
[ 1.2000]], requires_grad=True)
30.2 A simple network
30.2.1 Synthetic Data
np.random.RandomState= np.random.rand(500, 10)
x = np.random.rand(10)
w = x @ w + np.random.rand(500)/10 y
= np.random.choice(range(500), 400, replace=False)
res = x[res]
x_train = y[res]
y_train = np.delete(x, res, axis = 0)
x_test = np.delete(y, res, axis = 0) y_test
x_train.shape, x_test.shape
((400, 10), (100, 10))
30.2.2 Network
import torch
import torch.nn as nn
import torch.nn.functional as F
= torch.from_numpy(x_train).float()
x_tr = torch.from_numpy(y_train).float()
y_tr = torch.from_numpy(x_test).float()
x_te = torch.from_numpy(y_test).float() y_te
x_tr.size(), y_tr.size()
(torch.Size([400, 10]), torch.Size([400]))
x_tr.dtype, y_tr.dtype
(torch.float32, torch.float32)
30.2.3 Train
# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
= 50, 10, 10, 1
N, D_in, H, D_out
# Create random Tensors to hold inputs and outputs
# x = torch.randn(N, D_in)
# y = torch.randn(N, D_out)
# Use the nn package to define our model and loss function.
= torch.nn.Sequential(
model
torch.nn.Linear(D_in, H),
torch.nn.ReLU(),
torch.nn.Linear(H, D_out),
)= torch.nn.MSELoss(reduction='sum')
loss_fn
# Use the optim package to define an Optimizer that will update the weights of
# the model for us. Here we will use Adam; the optim package contains many other
# optimization algorithms. The first argument to the Adam constructor tells the
# optimizer which Tensors it should update.
= 1e-2
learning_rate = torch.optim.Adam(model.parameters(), lr=learning_rate)
optimizer for t in range(500):
# Forward pass: compute predicted y by passing x to the model.
= model(x_tr)
y_pred
# Compute and print loss.
= loss_fn(y_pred, y_tr)
loss if t % 100 == 99:
print(t, loss.item())
# Before the backward pass, use the optimizer object to zero all of the
# gradients for the variables it will update (which are the learnable
# weights of the model). This is because by default, gradients are
# accumulated in buffers( i.e, not overwritten) whenever .backward()
# is called. Checkout docs of torch.autograd.backward for more details.
optimizer.zero_grad()
# Backward pass: compute gradient of the loss with respect to model
# parameters
loss.backward()
# Calling the step function on an Optimizer makes an update to its
# parameters
optimizer.step()
/Users/egenn/sw/miniforge3/envs/rtemis/lib/python3.10/site-packages/torch/nn/modules/loss.py:530: UserWarning:
Using a target size (torch.Size([400])) that is different to the input size (torch.Size([400, 1])). This will likely lead to incorrect results due to broadcasting. Please ensure they have the same size.
99 85912.296875
199 79523.796875
299 73427.34375
399 67984.4921875
499 64096.19140625