AI Hints
Home›Deep Learning Tutorial›Optimisers and Learning Rates
Deep Learning · Lesson 15 of 92

The Learning Rate

The most important dial.

⏱ 2 min read▶ Video at 31:10🎓 Free
Watch this lesson in the Deep Learning courseWatch on YouTube ↗Full Deep Learning course

Ask any experienced deep learning engineer which setting they'd tune if they could only choose one. They'll all give the same answer. It's the learning rate. It's also the first thing to check when training goes wrong.

The Learning Rate
From the video: The Learning Rate
  • If you could tune just one
  • Everyone gives the same answer
  • First thing to check

Four learning rates

We train one epoch, with four different rates. Run it. Look at the results. Point zero zero zero zero one is so small that the model has barely learned. Point zero zero one works well. Point zero one is still fine, on this easy problem. And at one, training has collapsed completely, to a score close to random guessing. Far too big, and the weights fly apart. That's what a broken learning rate looks like.

learning_rates.pypython
import torch
from torch import nn
from torchvision import datasets, transforms

root = "data"
tf = transforms.ToTensor()
train = datasets.FashionMNIST(root, train=True, transform=tf)
test = datasets.FashionMNIST(root, train=False, transform=tf)
X_test = test.data.float().unsqueeze(1) / 255

def run(make_opt, epochs=2, seed=0, net=None, scheduler=None):
    torch.manual_seed(seed)
    model = net() if net else nn.Sequential(nn.Flatten(), nn.Linear(784, 256),
                                            nn.ReLU(), nn.Linear(256, 10))
    opt = make_opt(model.parameters())
    dl = torch.utils.data.DataLoader(train, batch_size=128, shuffle=True)
    for _ in range(epochs):
        model.train()
        for x, y in dl:
            loss = nn.functional.cross_entropy(model(x), y)
            opt.zero_grad(); loss.backward(); opt.step()
    model.eval()
    with torch.no_grad():
        return (model(X_test).argmax(1) == test.targets).float().mean().item()

from torch.optim import Adam

for lr in [1e-5, 1e-3, 1e-2, 1.0]:
    print(f"lr {lr:<7} accuracy {run(lambda p: Adam(p, lr=lr), epochs=1):.3f}")
Output
lr 1e-05   accuracy 0.652
lr 0.001   accuracy 0.842
lr 0.01    accuracy 0.818
lr 1.0     accuracy 0.181

Warm up, then cool down

The best learning rate actually changes over time. At the start, the weights are random, so big jumps can be dangerous. We warm up slowly, for a short time. Then, as we approach a good solution, we need finer and finer steps. So we slowly cool down, often along a smooth cosine curve. This warm up and cosine schedule is used to train nearly all modern large models.

A schedule in code

PyTorch has schedulers built in. We create one for the linear warm up, and one for the cosine decay, and chain them together. Each training step, we call sched dot step. Run it. The rate climbs for the first ten steps, then glides down towards zero. You'd normally use this inside the training loop, right after the optimiser step.

schedule.pypython
import torch
from torch import nn

model = nn.Linear(10, 1)
opt = torch.optim.AdamW(model.parameters(), lr=0.001)
steps = 100
warm = torch.optim.lr_scheduler.LinearLR(opt, 0.1, 1.0, total_iters=10)
cos = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=steps - 10)
sched = torch.optim.lr_scheduler.SequentialLR(opt, [warm, cos], milestones=[10])

for step in range(steps):
    opt.step()
    sched.step()
    if step in (0, 9, 30, 60, 99):
        print(f"step {step:>2}  lr {opt.param_groups[0]['lr']:.6f}")
Output
step  0  lr 0.000190
step  9  lr 0.001000
step 30  lr 0.000872
step 60  lr 0.000396
step 99  lr 0.000000

Summary

Too small, and you wait forever. Too large, and everything explodes. And a warm up with a cosine decay gets the best of both. Next, a hidden trap that can ruin training before the first step. How you start your weights.

Key takeaways
  • Tune the learning rate first
  • Too big explodes, too small crawls
  • Warm up, then cosine decay
Next up: Weight Initialisation — starting in the right place