Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Overfitting and early stopping

After this lesson: I can spot overfitting and stop training before it gets worse.

55 min lesson2 commandsJupyterLab data science lab: pandas, Matplotlib and scikit-learn in the browser

A network that memorised the year

Overfitting happens when a neural network learns its training examples so closely that it does badly on new ones. Spotting it, and stopping training at the right moment, separates a model that works in a demo from one that works in a shop.

A network with enough weights can memorise a whole year of bike hires, the random noise included.

By the end of this lesson

Note

I can spot overfitting and stop training before it gets worse.

Key words

WordWhat it meansExample
Training setthe rows used to set the weights
Validation setrows kept back to check on unseen data
Overfittinglearning the training rows, noise and all
Early stoppingending training once validation stops improving
Patiencehow many epochs to wait for a new best3

The cells students fill in are left blank in this preview.

Keep some rows back to test the network

A network is judged on rows it has never seen. So you split the data first. The training set sets the weights. The validation set is kept back, and you only use it to measure the loss.

A common split is 80 percent for training and 20 percent for validation. A year of 365 days gives 292 and 73.

Worked example: splitting a year of 365 days

SetShareDaysUsed for
Training set80 percent292Setting the weights
Validation set20 percent73Checking on days it has not seen

The cells students fill in are left blank in this preview.

Count the lines of the bike file

Command
docker exec jupyter wc -l hires.csv

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Work out the two set sizes

Command
docker exec jupyter python3 -c "print(int(365 * 0.8), 365 - int(365 * 0.8))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Overfitting shows up as a growing gap

Early in training both losses fall. Then the network starts to fit the noise in the training rows. The training loss keeps falling, but the validation loss stops falling and starts to rise.

The distance between the two is the gap. A growing gap is the sign of overfitting.

Worked example: eight epochs of training

EpochTraining lossValidation lossGap
19.09.50.5
26.06.50.5
34.04.80.8
42.54.01.5
51.53.82.3
60.94.03.1
70.54.54.0
80.25.25.0

The cells students fill in are left blank in this preview.

Find the best epoch in Python

Code: python
train = [9.0, 6.0, 4.0, 2.5, 1.5, 0.9, 0.5, 0.2]
validation = [9.5, 6.5, 4.8, 4.0, 3.8, 4.0, 4.5, 5.2]

best = validation[0]
best_epoch = 1
for n in range(8):
    gap = validation[n] - train[n]
    print("epoch", n + 1, "gap", round(gap, 1))
    if validation[n] < best:
        best = validation[n]
        best_epoch = n + 1
print("best epoch:", best_epoch)
# Change the last validation loss from 5.2 to 3.0 and press Run.
# Which epoch is best now?

Early stopping ends training at the right time

Early stopping ends training once the validation loss has stopped improving. Patience is how many epochs in a row you wait without a new best before you stop.

Then you keep the weights from the best epoch, not the last one. The last ones have already started to overfit.

Worked example: stopping with patience 2 and 3

EpochValidation lossNew bestWaitedStops with
53.8yes0nothing yet
64.0no1nothing yet
74.5no2patience 2
85.2no3patience 3

The cells students fill in are left blank in this preview.

More ways to reduce overfitting

Early stopping is one fix. Dropout switches off a random share of neurons at each training step, so none can lean on another. A weight penalty adds a cost to the loss for large weights.

You can also add more data, or use a smaller network that has fewer weights to memorise with.

Type this in your notebook: two sizes

Code: python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import StandardScaler

hires = pd.read_csv("hires.csv")
hires["weekend"] = hires["weekday"].isin(["Sat", "Sun"]).astype(int)
label = (hires["hires"] >= 300).astype(int)
X = StandardScaler().fit_transform(hires[["temp_c", "rain_mm", "weekend"]])
X_train, X_val, y_train, y_val = train_test_split(X, label, test_size=0.2, random_state=1)

for size in [(2,), (64, 64)]:
    net = MLPClassifier(hidden_layer_sizes=size, max_iter=3000, random_state=0)
    net.fit(X_train, y_train)
    print(size, "training:", round(net.score(X_train, y_train), 3),
          "validation:", round(net.score(X_val, y_val), 3))
# Then add early_stopping=True to MLPClassifier and run it again.

A common mistake

Warning

Many people think the model with the highest training score is the best one. A network can score 100 percent on rows it has seen by memorising them. Only the score on rows it has not seen shows whether it learned the pattern. Always read the two scores side by side.

Going further

A final test set is a third group of rows that you use once, at the very end. Why can you not use the validation set for that job?

Hint: you chose the stopping epoch by looking at the validation loss, so the validation set has already helped to pick the model.

About this lab and its source: JupyterLab data science lab: pandas, Matplotlib and scikit-learn in the browser

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.