Early stopping
Keep watching validation loss. Stop training—or restore an earlier model—when validation performance stops improving.
It changes how long we train.
One new idea, built on Chapter 4
Early stopping asks when should training end? Regularization asks a different question: while training, can we make extremely large weights a little less attractive?
In the HW3 experiment, training loss may keep falling after validation loss begins to rise. The model is getting better at its training examples without getting better at new examples.
Keep watching validation loss. Stop training—or restore an earlier model—when validation performance stops improving.
It changes how long we train.
Add another preference to the training objective: fit the examples, but avoid using unnecessarily large weights.
It changes what training tries to minimize.
Chapter 4 describes loss as a number we want to make small. A regularized training objective is still one number—it simply combines two concerns.
This toy model has just one weight. The data alone prefers weight = 4. Move the slider to make large weights increasingly expensive.
Notice what regularization does not say: it does not claim that small weights are automatically correct. It says that, when two settings fit the training data similarly, we prefer the one that relies less on large weights.
The forward pass stays the same. The loss gains one extra calculation before `backward()`.
for xb, yb in dl:
predictions = model(xb)
data_loss = mnist_loss(predictions, yb)
weight_penalty = (weights ** 2).mean()
loss = data_loss + strength * weight_penalty
loss.backward()
weights.data -= weights.grad * lr
bias.data -= bias.grad * lr
weights.grad.zero_()
bias.grad.zero_()
The total loss depends on both the predictions and the weights. `backward()` therefore includes both influences when it calculates `weights.grad`.
For this first experiment, penalize the weights and leave the bias alone. That keeps the question focused. Larger systems may make different choices.
When using PyTorch’s SGD optimizer, the same idea is available as `weight_decay`:
optimizer = torch.optim.SGD(model.parameters(), lr=lr, weight_decay=strength)
For this Chapter 4 extension, writing the penalty explicitly makes the changed objective easier to inspect. PyTorch documents SGD’s weight_decay option as an L2 penalty. The numerical value of `strength` need not match `weight_decay` exactly because a hand-written penalty may use a sum or a mean.
A regularizer is useful only if held-out evidence improves. Keep everything else fixed.
| Method | What changes? | Question it answers |
|---|---|---|
| Early stopping | The epoch at which training ends | When did validation performance stop improving? |
| L2 regularization | The objective minimized during every update | Can a model fit reasonably well without relying on large weights? |
Starting from your overfitting run, add an L2 penalty to the training loss. Keep the data split, model, learning rate, and epoch count fixed.