Machine learning for energy data · Lesson 9 of 13
Overfitting and regularisation
An example lesson built by Chalkwork Labs from public sources, to show the shapes. Your course is drafted from your material and checked by you.
A model can look brilliant on the data it learned from and fail on the next day's data. This lesson shows why, on two years of real British electricity demand. You will bend a curve too far, watch it break, and then use one knob to fix it.
1. What overfitting is, in plain words
Imagine a student who prepares for an exam by memorising last year's answer sheet. On last year's questions they score 100%. On this year's questions they fail. They did not learn the subject. They learned the sheet.
A model can do the same. Overfitting means a model has fitted the noise in its training data as if it were a pattern. It then does worse on new data. The opposite is underfitting: a model too simple to follow even the real pattern.
Here is the data for this lesson. Each dot is one working day in 2023 or 2024. Across is the day's mean temperature in central England. Up is Great Britain's mean electricity demand that day.
The pattern is clear. Cold days need heating, so demand is high on the left. Demand falls as it gets warmer. Above about °C it flattens and may turn up a little, as fans and cooling come on. Only % of days are warmer than that, so the right-hand end is thin.
The question for a model is: given the temperature, what will demand be? Temperature is the input. Demand is the output we want to predict. The model is a curve through the cloud.
No curve passes through every dot. Some scatter is real: school holidays, the economy, a cloudy afternoon. A good model follows the pattern and ignores the scatter. An overfitted model chases the scatter.
2. Two errors, not one
To catch overfitting you need two numbers, not one. First, split the days into two groups. The train/test split puts most days into a training set, which the model learns from, and keeps the rest as a test set, which the model never sees. Here the split is random: training days and test days.
- The training error is the model's average miss on the days it learned from.
- The test error is its average miss on the days it has never seen.
- The difference is the generalisation gap. A big gap is the signature of overfitting.
The error itself is the mean absolute error: take each day's gap between prediction and truth, drop the sign, and average. It is in GW, the same unit as demand. Lower is better.
A straight line through the cloud gives a training error of GW and a test error of GW. A curve with one bend gives GW and GW. Both numbers moved. The test number is the one that matters, because tomorrow is always unseen.
The training error alone tells you nothing. Any model with enough freedom can drive it to zero by memorising. Only the test error measures learning.
3. Be the model: how many bends?
The model here is a polynomial: a curve built from temperature, temperature squared, temperature cubed, and so on. Its degree is the highest power it uses. Degree 1 is a straight line. Degree 2 has one bend. Degree 12 may have up to eleven bends.
The degree is a hyperparameter: a setting you choose before the model learns. The model then learns the best numbers in front of each power. You choose the freedom. The data chooses the shape.
Move the controls. The curve is refitted live, and both errors update.
Try these in order:
- Degree 1, then 2, then 3, with all training days. The test error falls as the curve gets the bend it needs.
- Degree 12, still with all days. The curve wiggles at the ends but the test error barely moves: GW. With days and 12 numbers to learn, there is little room to memorise.
- Degree 12 with 40 training days. The curve leaves the chart. The training error is still GW. The test error is GW. That is overfitting: the curve chases 40 dots and has no idea what to do between or beyond them.
- Degree 2 with 40 days. Test error GW. A simple curve learns the pattern from a few days. A flexible one needs many.
Overfitting is about freedom relative to data. Twelve bends on 353 days is fine. Twelve bends on 40 days is memorising. The same model is honest or dishonest depending on how much data it has.
4. The validation curve: error against degree
Instead of one degree at a time, plot both errors for every degree from 1 to 12. This is a validation curve: error against a model setting, here the degree. It shows the whole trade in one picture. (A learning curve is a different picture: error against the number of training days. The training-days slider lets you trace that one too.)
Read the shape. The training error only ever falls, or stays flat, as the degree rises. More freedom always fits the training days at least as well. The test error falls, bottoms out, and then rises. The rise is overfitting. With all random training days the best degree is and the curve is nearly flat. With 40 days the best degree is low and the right-hand side explodes.
Switch the split to 2023 to 2024. The model learns one year and is tested on the next. The best test error is now GW at degree , against GW under the random split. An unseen year is a harder test than unseen days from the same years. Why? Open question. Candidates: 2024 demand was a little lower overall, and the two years had different cold spells.
5. Regularisation: pay for every bend
Regularisation is any rule that limits a model's freedom so that it cannot fit noise. For a polynomial, the usual rule is a penalty on big coefficients. The model pays a price for every large number in front of a power. The strength slider sets that price. At 0 there is no penalty. At 1,000 the penalty is so heavy that the curve is pulled almost flat.
This is the fix for the 40-day disaster. Degree 12 on 40 training days, at each strength:
| Strength | training error (GW) | test error (GW) |
|---|
At strength the test error is GW, down from GW. The training error went up, from to GW. That is the trade. Regularisation costs training error and buys test error. Push it too far and the curve is too stiff to follow the real pattern: strength 1,000 underfits.
Go back to the chart in section 3. Set degree 12 and 40 days, then raise the strength step by step. Watch the curve calm down.
Regularisation only matters when the model has room to overfit. Try strength 10 with all days at degree 12. The test error hardly moves. There was little noise being fitted, so there was little to fix.
6. A worked example: one cold day
Take the coldest test day under the random split: , mean temperature °C. Real demand that day was GW. Three models predict it:
| Model | prediction (GW) | miss (GW) | test error over all test days |
|---|---|---|---|
| Degree 2, all days, no regularisation | |||
| Degree 12, 40 days, no regularisation | |||
| Degree 12, 40 days, strength 10 |
The degree-2 model misses by GW, about twice its average miss, but its answer is at least a demand-like number. The overfitted model predicts a number that is not demand at all. The regularised model is sane on average but still far off on this day. Why? The 40 training days run from °C to °C. This day, at °C, is colder than anything the model has seen. No amount of regularisation can teach a model about temperatures that are not in its data. Only more data can.
Quick check
1. A model scores 0.3 GW on its training days and 4.0 GW on test days. What is the most likely explanation?
2. Degree 12 gives a fine test error on 353 training days and a terrible one on 40. What changed?
3. You raise the regularisation strength and the training error goes up. Is that a problem?
7. Read the code
Each block holds real Python that runs in this page. You will not write or edit any of it. Read the steps, press Run, then answer the question under the block. Lines starting with # are notes. Python ignores them.
Block 1: The table and the split
Read the three steps, then press Run. Check that the two counts match section 2.
- Look at the table. One row per working day: date, temperature and demand. Each row is already marked as a training or test day.
- Split the table into the two groups. The training rows come first, in a shuffled order, so "the first 40" is a random sample.
- Print the size of each group.
Block 2: The fit recipe
This is the model in sections 3 and 4, written out. Read the four steps, then press Run. The two errors should match the degree-2 numbers in section 2.
- Turn a list of temperatures into columns: temperature, temperature squared, and so on up to the degree. The temperature is first put into standard units, so that the powers stay a sensible size.
- Fit: scale each column, add the penalty
alphato the diagonal, and solve for the coefficients. Withalpha = 0this is plain least squares. A bigger alpha pulls every coefficient towards zero. - Predict: build the same columns for new temperatures and combine them with the learned coefficients.
- Fit a degree-2 curve on the training days with no penalty, then score it on both groups.
The test error (1.52 GW) is a little higher than the training error (1.45 GW). What does that tell you?
Block 3: Try values. Degree, strength and data
The controls set the three numbers at the top of the code. Start as it is: degree 12 on 40 days with no penalty. Then raise the strength to 1, 10 and 100. Then set the days to 353 and the strength back to 0.
At strength 10 the training error rose from 1.03 to 1.71 GW and the test error fell from 669 to 3.21 GW. Which statement is right?
Spot the mistake
Someone picks the degree like this. It runs, and the number looks good. Click the line whose idea is wrong.
- Starting with nothing chosen is fine.
- Trying every degree from 1 to 12 is a sensible search. The problem is how each one is judged.
- Fitting on the training days is right.
- Each degree is judged on the test days. So the degree was chosen by peeking at the test set twelve times, and the final 1.36 GW is the best of twelve peeks, not an honest estimate. The honest way: hold back a slice of the training days, pick the degree on that slice, then score the test days once. Done that way here, the slice picks degree 8 and the one honest test score is 1.38 GW.
- Keeping the lowest error is the right way to pick a winner. The data it is measured on is the problem.
- Storing the winner is fine.
- Printing the result is fine. The number itself is flattered.
What to remember
- Overfitting is fitting the noise. The model looks good on the days it learned from and bad on new days.
- Always measure two errors. The training error alone can be driven to zero. Only the test error measures learning.
- The gap between them is the warning sign.
- Freedom is only a problem relative to data. Twelve bends on 353 days is fine. Twelve bends on 40 days is memorising.
- Regularisation charges the model for every bend. It raises the training error and, when there was noise being fitted, lowers the test error.
- Never choose a setting by looking at the test set. Use a slice of the training data, then score the test set once.
- No model can know about conditions that are not in its data. A cold day colder than any training day will be missed.
Sources
- NESO, Historic Demand Data, 2023 and 2024 files, column ND (national demand, MW, half-hourly). NESO Open Data Licence, which is the Open Government Licence v3.0 with NESO amendments.
- Met Office Hadley Centre, Central England Temperature (HadCET), daily mean series. Open Government Licence. Please acknowledge the source if you reuse the data.
- Processing: weekdays only, with the 17 English bank holidays of 2023 and 2024 removed (GOV.UK list); demand averaged over each day's 48 half-hours and shown in GW; days joined to temperature by date. The script that builds every number on this page is
export_01.pyin the course folder.