Skip to main content

Deep Learning with PyTorch

PyTorch is a flexible deep learning library with automatic differentiation.

Tensors and autograd​

import torch

x = torch.tensor([2.0, 3.0], requires_grad=True)
y = (x ** 2).sum()
y.backward()
print(x.grad) # tensor([4., 6.]) (dy/dx = 2x)

The training loop​

import torch
from torch import nn
from torch.utils.data import DataLoader, TensorDataset

# toy data
X = torch.randn(1000, 20)
y = (X[:, 0] + X[:, 1] > 0).long()
train_dl = DataLoader(TensorDataset(X[:800], y[:800]), batch_size=64, shuffle=True)
test_dl = DataLoader(TensorDataset(X[800:], y[800:]), batch_size=128)

model = nn.Sequential(nn.Linear(20, 64), nn.ReLU(), nn.Dropout(0.2), nn.Linear(64, 2))
loss_fn = nn.CrossEntropyLoss()
opt = torch.optim.Adam(model.parameters(), lr=1e-3)

for epoch in range(10):
model.train()
for xb, yb in train_dl:
opt.zero_grad()
loss = loss_fn(model(xb), yb)
loss.backward()
opt.step()

model.eval()
correct = 0
with torch.no_grad():
for xb, yb in test_dl:
correct += (model(xb).argmax(1) == yb).sum().item()
print(f"epoch {epoch}: test acc {correct / len(test_dl.dataset):.3f}")

A small CNN for images​

class SmallCNN(nn.Module):
def __init__(self, classes=10):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2), # 28 -> 14
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2), # 14 -> 7
)
self.head = nn.Sequential(nn.Flatten(), nn.Linear(32 * 7 * 7, 128), nn.ReLU(), nn.Linear(128, classes))

def forward(self, x):
return self.head(self.features(x))

Making training work​

ProblemRemedy
OverfittingMore data, augmentation, dropout, weight decay, early stopping
Unstable lossLower learning rate, gradient clipping, normalise inputs
Slow trainingGPU (model.to("cuda")), larger batches, mixed precision
Poor resultsStart with a pretrained model (transfer learning)
TIP

Always overfit a tiny batch first. If the model cannot memorise 10 examples, there is a bug in the pipeline, not a tuning problem.