AI Hints
Home›Deep Learning Tutorial›Training Craft
Deep Learning · Lesson 19 of 92

Checkpoints and Early Stopping

Never lose a training run.

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

Three days into a training run, at ninety percent complete, the power goes out. Every deep learning engineer has a story like this one. And it only happens once, because after that, you never train anything without saving as you go.

Checkpoints and Early Stopping
From the video: Checkpoints and Early Stopping
  • Day three of training
  • The power goes out
  • It only happens once

Knowing when to stop

Look at these two curves. Training loss keeps falling, forever. But validation loss falls, and then it turns and starts to rise. That's overfitting, in action. The best model is at the bottom of the orange curve, not at the end of training. Early stopping watches this curve, and it stops the run when things stop improving.

An early stopper

Here's a small class that does this. Each epoch, it receives the validation loss. If that's a new best, it saves a copy of the model, and resets its counter. If not, it adds to the counter. And after too many bad epochs in a row, it says stop. We feed it a pretend history. Run it. It stops at epoch six, and keeps the model from epoch four. We get the best version, not just the last one.

early_stop.pypython
import copy

class EarlyStopper:
    def __init__(self, patience=3):
        self.patience, self.best, self.bad = patience, float("inf"), 0
        self.state = None

    def step(self, val_loss, model_state):
        if val_loss < self.best:
            self.best, self.bad = val_loss, 0
            self.state = copy.deepcopy(model_state)
            return False
        self.bad += 1
        return self.bad >= self.patience

stopper = EarlyStopper(patience=2)
history = [0.9, 0.7, 0.55, 0.48, 0.5, 0.53]

for epoch, loss in enumerate(history, 1):
    stop = stopper.step(loss, {"epoch": epoch})
    print(f"epoch {epoch}  val loss {loss}  stop? {stop}")
    if stop:
        break
print("Best model came from:", stopper.state)
Output
epoch 1  val loss 0.9  stop? False
epoch 2  val loss 0.7  stop? False
epoch 3  val loss 0.55  stop? False
epoch 4  val loss 0.48  stop? False
epoch 5  val loss 0.5  stop? False
epoch 6  val loss 0.53  stop? True
Best model came from: {'epoch': 4}

Saving a checkpoint

A checkpoint needs more than the weights. To resume training properly, you also need the optimiser's state, and the epoch number. State dict gives you a dictionary of all weights. Torch save writes it all to one file. To resume, we load it, and pour the weights into a fresh model. Run it. The weights are identical, and we can carry on from epoch seven. Save a checkpoint at each epoch, and keep the best one.

checkpoint.pypython
import torch
from torch import nn

model = nn.Linear(4, 2)
opt = torch.optim.AdamW(model.parameters())

torch.save({"epoch": 7, "model": model.state_dict(),
            "optimiser": opt.state_dict()}, "checkpoint.pt")

saved = torch.load("checkpoint.pt", weights_only=True)
fresh = nn.Linear(4, 2)
fresh.load_state_dict(saved["model"])

same = torch.equal(model.weight, fresh.weight)
print("Resuming from epoch:", saved["epoch"])
print("Weights identical:", same)
Output
Resuming from epoch: 7
Weights identical: True

Making runs repeatable

One last habit. Neural networks use randomness everywhere, in initial weights, in shuffling, and in dropout. If two runs differ, you can't tell whether your change helped. Setting the seeds at the start makes results repeatable. Run it. The same seed gives the same numbers. Even then, runs on a G P U can differ slightly, so for serious comparisons, average over a few seeds.

seeds.pypython
import random
import numpy as np
import torch

def set_seed(seed):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)

set_seed(42)
a = torch.rand(3)
set_seed(42)
b = torch.rand(3)
print("Same numbers:", torch.equal(a, b))
Output
Same numbers: True

Summary

Save checkpoints, stop early, and set your seeds. That's the difference between an experiment and a mess. You now have a complete training toolkit. Next, it's time to take on images, with an idea borrowed from the human visual system.

Key takeaways
  • Early stopping keeps the best model
  • Checkpoint weights and optimiser
  • Seeds make results repeatable
Next up: Why Images Need Convolutions — the problem with flat networks