Quant Memo
Core

Early Stopping Criteria and Patience

Rather than training for a fixed number of steps, early stopping watches performance on held-out data and stops once it stops improving — the tricky part is deciding how many bad epochs in a row you're willing to tolerate before giving up.

Prerequisites: Overfitting, Cross-Validation for Time Series

Training loss almost always keeps falling the longer you train — a model with enough capacity can eventually memorize the training set nearly perfectly. But loss on held-out data the model has never seen typically falls for a while, then starts rising again, as the model shifts from learning genuine patterns to memorizing training-set quirks. Training for a fixed, arbitrarily chosen number of epochs risks stopping too early, before the model has learned enough, or too late, after it has already started overfitting. Early stopping instead watches validation performance directly and stops training when that number stops improving.

The analogy: tasting soup while it simmers

A cook adjusting a soup by taste doesn't set a timer and walk away — they taste it periodically as it simmers, and stop the moment it goes from "still improving" to "getting worse" (over-reduced, over-salted). Stopping the instant the very first spoonful tastes slightly worse than the last would be jumpy — taste can wobble spoonful to spoonful even while the soup is still generally improving. So a sensible cook tolerates a few slightly-worse tastes in a row before concluding the soup has actually turned, rather than reacting to the very first blip. That tolerance for a few bad tastes in a row is exactly what "patience" means in early stopping.

The mechanics: monitor, track the best, wait out the noise

At the end of every epoch, evaluate the model on a held-out validation set and record the validation loss LvalL_{\text{val}}. Track the best (lowest) validation loss seen so far, LbestL_{\text{best}}, and a counter of how many epochs in a row have failed to beat it:

if Lval<Lbest: LbestLval, counter0else: countercounter+1\text{if } L_{\text{val}} < L_{\text{best}}: \ L_{\text{best}} \leftarrow L_{\text{val}}, \ \text{counter} \leftarrow 0 \qquad \text{else}: \ \text{counter} \leftarrow \text{counter}+1

In words: whenever validation loss sets a new best, save that epoch's weights and reset the "epochs since improvement" counter to zero; whenever it fails to improve, increment the counter. Training stops once the counter reaches a chosen threshold called patience — the number of consecutive non-improving epochs tolerated before concluding the model has genuinely stopped improving rather than just having one noisy epoch. The final model used is not the one from the last epoch trained, but the one saved at LbestL_{\text{best}}.

Worked example 1: patience of 3 stops training

Validation loss across epochs: 2.0,1.8,1.7,1.75,1.72,1.80,1.852.0, 1.8, 1.7, 1.75, 1.72, 1.80, 1.85, with patience =3=3. Epoch 1: loss 2.02.0, new best, counter =0=0. Epoch 2: 1.8<2.01.8 < 2.0, new best, counter =0=0. Epoch 3: 1.7<1.81.7 < 1.8, new best, counter =0=0. Epoch 4: 1.75>1.71.75 > 1.7, no improvement, counter =1=1. Epoch 5: 1.72>1.71.72 > 1.7, still no improvement (doesn't beat the best, 1.71.7), counter =2=2. Epoch 6: 1.801.80, counter =3=3 — patience threshold hit, training stops. The model saved and returned is the one from epoch 3, where validation loss 1.71.7 was the best ever recorded, not the epoch 6 model that triggered the stop.

Worked example 2: patience too low reacts to noise

Same validation sequence, but patience =1=1. Epoch 4's non-improvement (1.75>1.71.75 > 1.7) immediately hits the patience threshold, and training stops right there — missing epoch 5's 1.721.72, which, while not a new best, would have shown the model was still hovering near its best rather than clearly worsening. A patience this low can stop training prematurely on a single noisy epoch, before the model has had a fair chance to continue improving after a brief wobble.

Gradient descent
parameter →
position -0.623loss -0.141gradient -0.930converging

best (saved) stop triggered (patience=3)
Validation loss bottoms out, then drifts upward for several epochs before patience is exhausted; the saved model comes from the true minimum, not the stopping point.

What this means in practice

Early stopping is one of the cheapest and most broadly used forms of regularization — it costs almost nothing beyond periodic validation evaluation and requires no change to the model or loss function. Patience is itself a hyperparameter to tune: too low, and training stops on noise before real improvement resumes; too high, and you waste substantial compute training well past the point where the model was already at its best, though that waste is usually far cheaper than the alternative of overfitting badly.

Early stopping tracks the best validation performance seen so far and halts training once a chosen number of consecutive non-improving epochs (patience) has passed, but the model actually used is the one saved at the best point, not the one present when training stopped.

Practice

  1. Validation losses are 3.0,2.5,2.6,2.4,2.6,2.73.0, 2.5, 2.6, 2.4, 2.6, 2.7 with patience =2=2. At which epoch does training stop, and which epoch's weights are kept?
  2. Why is a patience of exactly 0 (stop the instant validation loss fails to improve) usually a bad idea?
  3. Name one situation where a very noisy validation metric would argue for a higher patience value.

The most common mistake is deploying the weights from the epoch training happened to stop at, rather than the epoch that actually achieved the best validation score. Because patience deliberately lets training run several epochs past the true best before stopping, the final-epoch weights are, by construction, from a point already partway back into overfitting — always save and restore the best checkpoint, not the last one.

Related concepts

Practice in interviews

Further reading

  • Prechelt, Early Stopping — But When? (2012)
ShareTwitterLinkedIn