Week 3 · principles
Suppose a classifier reaches 100% training accuracy.
What can we conclude about a new example drawn tomorrow?
Generalisation is the extent to which performance carries from the training data to unseen data drawn from the relevant distribution.
MNIST is a classic machine-learning benchmark for recognising handwritten digits.
MNIST became useful because it provided a standard, easy-to-understand classification problem on which learning methods could be compared.
MNIST-1D is a synthetic, one-dimensional analogue of MNIST.
It is not a flattened or compressed MNIST image.
Instead of recognising a digit from a \(28\times28\) image, the model recognises a class from the shape of a short 1D signal.
Top: one handwritten MNIST test image of each digit, 28 × 28 pixels. Second row: the ten MNIST-1D templates, the whole vocabulary of the 1D dataset. Below each, two MNIST-1D training examples of that class, each a sequence of 40 values – all the network is given. MNIST images © Yann LeCun and Corinna Cortes, CC BY-SA 3.0.
We want to experiment with generalisation, not merely report one benchmark score.
MNIST-1D is useful because it is:
Treat it as a laboratory: change one part of the learning problem and observe what happens to training and generalisation.
We begin with:
Reminder: softmax and cross-entropy
The network produces 10 logits. Softmax converts them into 10 class probabilities.
Cross-entropy rewards assigning more probability to the correct class.
After roughly 4000 optimisation steps,
\[ \text{training classification error}=0. \]
The network correctly classifies every training example.
But that is not yet the question we care about:
What happens on new examples generated by the same process?
The fitted model has already had access to the training examples through optimisation.
A separate held-out set measures behaviour on examples that did not choose the model parameters.
For the MNIST-1D experiment:
An error near \(40\%\) is far below the \(90\%\) random-guessing baseline, but still far above the \(0\%\) training error.
This establishes that training fit and generalisation are different measurements. It does not yet tell us why the gap exists.
The same run scored two ways on two datasets. Left: classification error. Right: cross-entropy loss. Blue is the training set, coral the held-out evaluation set.
For multiclass classification:
Recall: what cross-entropy notices
For one labelled example, \(\loss_i=-\log p(y_i\mid\vect{x}_i)\).
So cross-entropy distinguishes how much probability the model assigns to the true class even when the predicted class itself does not change.
For a three-class problem with true class A:
| \(p(A)\) | \(p(B)\) | \(p(C)\) | predicted class | \(-\log p(A)\) |
|---|---|---|---|---|
| \(0.20\) | \(0.60\) | \(0.20\) | B | \(1.61\) |
| \(0.05\) | \(0.80\) | \(0.15\) | B | \(3.00\) |
| \(0.005\) | \(0.900\) | \(0.095\) | B | \(5.30\) |
The classification error is unchanged, but the model becomes increasingly confident in the same wrong class.
In the MNIST-1D run:
Classification error changes little, while wrong predictions can receive increasingly extreme probabilities.
The logits — the pre-softmax activations — become increasingly extreme as training pushes the probability of the correct training labels towards one.
A large gap can be consistent with:
The gap is evidence to investigate, not a diagnosis by itself.
MNIST-1D showed us that a generalisation gap can exist. It did not tell us what produced that gap.
To separate possible causes, move temporarily to a synthetic 1D regression problem where we control the data-generating process:
Now we know the underlying mean, choose the noise process, and can repeatedly draw new training datasets. That lets us isolate noise, bias, and variance rather than merely observe one aggregate error.
The mean function (ink), a band of two noise standard deviations either side of it, and one training set of noisy observations. Repeated outputs at the same input would scatter across the band, so even the mean itself misses them.
A joint is a point where a piecewise-linear function can change slope.
The simplified network fixes these joints at regular positions. With \(D\) hidden units, they occur at
\[ 0,\frac{1}{D},\frac{2}{D},\ldots,\frac{D-1}{D}. \]
Changing the remaining parameters produces a piecewise-linear function with \(D\) regions over \([0,1]\).
With these input-to-hidden parameters fixed, the remaining fitting problem has a closed-form solution.
That lets the experiment reach the global least-squares minimum directly, so changes in error can be attributed to data and capacity rather than stochastic optimisation failure.
At one fixed input \(x\), prediction error can reflect three different things:
| source | what varies? | intuition |
|---|---|---|
| noise | the observed \(y\) | valid outputs differ even when \(x\) is fixed |
| bias | the average fitted prediction | the learning procedure systematically misses the underlying mean |
| variance | the fitted model | a different training sample gives a different fitted function |
Bias and variance both concern the learning procedure across possible training datasets; variance is the spread around the average fitted predictor, while bias is the average predictor’s systematic offset from the underlying mean.
Left, noise: even the true mean misses fresh observations. Centre, bias: the best three-region fit cannot follow the mean, and the shading is its systematic error. Right, variance: fits to three different training sets of six points, each coloured with its own data.
Noise is variation in the data-generating process.
For a fixed input \(x\), there may be several valid observed outputs \(y\).
Noise can arise from:
Even a model that exactly recovers the conditional mean can still incur prediction error because the next observation is noisy.
Noise also need not prevent an extremely flexible model from fitting the training examples: if each input is observed only once, the model can memorise the particular noisy target it saw.
Irreducible here means irreducible given the observed input representation and the assumed task distribution.
Formally, bias compares the average fitted predictor across possible training datasets with the underlying conditional mean.
The toy model makes one important source of bias especially visible: even with abundant data and optimal fitting, a three-region piecewise-linear family cannot exactly reproduce the quasi-sinusoidal ground truth.
This is approximation bias from the model family. In the formal definition used here, bias belongs to the whole learning procedure, so systematic effects of fitting can also shift the average predictor.
Train the same model family several times on independently sampled datasets of the same size.
If the fitted functions differ substantially, the learning procedure has high variance with respect to the sampled training data.
Stochastic optimisation can add another source of run-to-run variation in practice.
The three-region model fitted to four independently drawn training sets of ten points, each fit coloured with its own data. The model family, the fitting rule and the data-generating process are the same every time; only the sample changes.
Bias asks:
If I could average away the accidents of the training sample, where would this learning procedure predict?
Variance asks:
How much would the fitted prediction move if I drew a different training sample?
Noise asks a third question:
Even if I knew the underlying mean exactly, how much would the next observed target vary?
Why separate them?
The same overall error can therefore imply different interventions.
We now have three intuitive sources of prediction error. For squared-error regression, we can ask a stronger question:
Can we show that
\[ \text{expected squared prediction error} = \text{noise} + \text{variance} + \text{squared bias}? \]
We will derive the result from two averages rather than treat it as a formula to memorise.
For a random variable \(Z\),
\[ \expect{Z} \]
is its mean or expected value.
Reminder: expectation
Expectation is a probability-weighted average. For a continuous variable, the corresponding weighted sum becomes an integral over its density.
The subscript tells us what is being averaged over:
A term that does not depend on the variable being averaged can be taken outside the expectation.
At a fixed input \(x\), keep two experiments separate:
Two independent draws from the same process. The upper branch samples a training set and fits a model; averaging over it retrains the model. The lower branch draws a fresh target at the fixed input; averaging over it holds the model fixed. The loss at x needs one of each.
Hold one input \(x\) fixed.
For continuous \(y\) with conditional density \(p(y\mid x)\), read \(p(y\mid x)\) as the distribution of possible outputs with this input held fixed, and define
\[ \mu[x] = \expectsub{y}{y[x]} = \int y[x]\,p(y\mid x)\,dy \]
as the conditional mean output at that input.
The notation \(y[x]\) emphasises that we are considering the random output at this particular input position.
Define the conditional noise variance at this input as
\[ \sigma^2[x] = \expectsub{y}{(y[x]-\mu[x])^2}. \]
The toy experiment uses a fixed Gaussian noise scale, but the decomposition itself does not require the same variance at every \(x\).
For one fitted model, the squared loss at \(x\) is
\[ \loss[x] = \left(\model{x}-y[x]\right)^2. \]
Reminder: squared loss
Squared loss measures the squared distance between a scalar prediction and its observed target. The square makes both positive and negative residuals contribute positively and penalises larger misses more strongly.
Add and subtract the conditional mean \(\mu[x]\):
\[ \loss[x] = \left( \underbrace{\model{x}-\mu[x]}_{\text{model versus mean}} + \underbrace{\mu[x]-y[x]}_{\text{observation noise}} \right)^2. \]
This is an exact identity.
Let
\[ a=\model{x}-\mu[x], \qquad b=\mu[x]-y[x]. \]
Then
\[ (a+b)^2=a^2+2ab+b^2. \]
So
\[ \loss[x] = (\model{x}-\mu[x])^2 +2(\model{x}-\mu[x])(\mu[x]-y[x]) +(\mu[x]-y[x])^2. \]
Average over possible fresh outputs \(y\) at this fixed \(x\).
Take \(\expectsub{y}{\cdot}\) while holding the fitted model fixed.
The factor \(\model{x}-\mu[x]\) does not depend on which fresh output \(y[x]\) is observed, so it leaves the expectation:
\[ \begin{aligned} &\expectsub{y}{2(\model{x}-\mu[x])(\mu[x]-y[x])}\\ &\qquad=2(\model{x}-\mu[x])\expectsub{y}{\mu[x]-y[x]}. \end{aligned} \]
By the definition \(\mu[x]=\expectsub{y}{y[x]}\),
\[ \expectsub{y}{\mu[x]-y[x]} = \mu[x]-\mu[x] =0. \]
The positive and negative observation deviations therefore cancel in expectation.
After the cross term vanishes,
\[ \boxed{ \expectsub{y}{\loss[x]} = \left(\model{x}-\mu[x]\right)^2 + \sigma^2[x] } \]
Two contributions remain:
The first contribution still mixes bias and variance because the fitted model depends on which training dataset we happened to observe.
Let the training dataset be
\[ \set{D}=\{(\vect{x}_i,y_i)\}_{i=1}^{I}. \]
Training on a different sample generally produces different parameters, so write
\[ \model[{\params[\set{D}]}]{x}. \]
For this derivation, hold the fitting procedure fixed and treat the learned model as deterministic once \(\set{D}\) is fixed. The outer expectation then varies the training dataset.
If optimisation itself is stochastic, run-to-run randomness adds another source of variability; it can be conditioned on separately or included in the outer averaging.
Define
\[ f_\mu[x] = \expectsub{\set{D}}{\model[{\params[\set{D}]}]{x}}. \]
Read this as:
train the same procedure on every possible dataset drawn from the process, predict at \(x\), then average those predictions
We do not have to be able to perform this experiment literally for the quantity to define what bias and variance mean.
Start from the remaining model-error term
\[ \left(\model[{\params[\set{D}]}]{x}-\mu[x]\right)^2. \]
Add and subtract \(f_\mu[x]\):
\[ \left( \underbrace{\model[{\params[\set{D}]}]{x}-f_\mu[x]}_{\text{sample-specific deviation}} + \underbrace{f_\mu[x]-\mu[x]}_{\text{systematic deviation}} \right)^2. \]
Again, this is an exact identity before taking expectations.
Expand and average over possible training datasets \(\set{D}\).
The factor \(f_\mu[x]-\mu[x]\) is fixed while the dataset varies, so the cross term becomes
\[ \begin{aligned} &\expectsub{\set{D}}{2(\model[{\params[\set{D}]}]{x}-f_\mu[x])(f_\mu[x]-\mu[x])}\\ &\qquad=2(f_\mu[x]-\mu[x])\expectsub{\set{D}}{\model[{\params[\set{D}]}]{x}-f_\mu[x]}. \end{aligned} \]
But \(f_\mu[x]\) is defined as that average, so
\[ \expectsub{\set{D}}{\model[{\params[\set{D}]}]{x}-f_\mu[x]} = f_\mu[x]-f_\mu[x] =0. \]
The sample-specific deviations cancel around the average fitted prediction.
We therefore obtain
\[ \expectsub{\set{D}}{\left(\model[{\params[\set{D}]}]{x}-\mu[x]\right)^2} = \underbrace{ \expectsub{\set{D}}{\left(\model[{\params[\set{D}]}]{x}-f_\mu[x]\right)^2} }_{\text{variance}} + \underbrace{ \left(f_\mu[x]-\mu[x]\right)^2 }_{\text{squared bias}}. \]
The pointwise bias itself is \(f_\mu[x]-\mu[x]\); the loss contribution is its square.
Combining the two splits gives
\[ \boxed{ \expectsub{\set{D}}{\expectsub{y}{\loss[x]}} = \underbrace{ \expectsub{\set{D}}{(\model[{\params[\set{D}]}]{x}-f_\mu[x])^2} }_{\text{variance}} + \underbrace{ (f_\mu[x]-\mu[x])^2 }_{\text{squared bias}} + \underbrace{\sigma^2[x]}_{\text{noise}} } \]
For least-squares regression, this is the exact additive decomposition.
Noise \(\sigma^2[x]\)
Squared bias \((f_\mu[x]-\mu[x])^2\)
Variance \(\expectsub{\set{D}}{(\model[{\params[\set{D}]}]{x}-f_\mu[x])^2}\)
If you forget the formula, reconstruct the ideas from the experiments:
The additive identity above assumes:
Noise, bias and variance remain useful concepts for other tasks, but they do not generally combine by this same three-term addition for arbitrary classification losses.
Equation 8.7 is pointwise in \(x\).
If inputs are themselves drawn from a distribution \(p(x)\), an overall expected squared error can average again over \(x\):
\[ \expectsub{x}{\expectsub{\set{D}}{\expectsub{y}{\loss[x]}}}. \]
The same three contributions are then averaged across the parts of the input space that the task actually visits. In particular, the overall noise contribution is \(\expectsub{x}{\sigma^2[x]}\).
This extra expectation is a generalisation of the fixed-\(x\) derivation, not a new fourth error source.
The decomposition tells us where expected error comes from. Now ask what we can change.
Two useful experimental levers are:
Hold the other ingredients fixed and vary one lever at a time.
Variance comes from sensitivity to the particular sampled training set.
Holding the task and model family fixed, increasing the number of training examples usually:
It does not remove irreducible noise or repair a model family with substantial bias.
In the toy experiment:
The variable being changed is dataset size, not architecture.
The three-region model fitted to twenty independent training sets at each size. The model family is the same in every panel; only the number of examples changes.
The toy model divides \([0,1]\) into piecewise-linear regions.
Adding hidden units creates more regions, so the family can represent a wider range of functions.
As capacity increases, the best attainable approximation can move closer to the underlying mean function.
That reduces bias in this example.
Capacity is about the set of behaviours the learning system can express or reach, not simply whether a network looks “large”.
Parameter count or hidden-unit count are convenient proxies, but several different notions of capacity matter:
Two systems with the same number of parameters can have different effective capacity because architecture, optimisation, regularisation and training time constrain what is reached.
With a fixed amount of noisy training data, a more flexible model can respond more strongly to sample-specific accidents.
In the classical regime:
A lower training error therefore need not imply lower held-out error.
Compare two capacities on the same noisy task:
When that extra fit captures noise or sample-specific structure rather than the underlying relationship, held-out performance can degrade.
That behaviour is overfitting.
A training/held-out gap alone still does not tell us whether this is the cause.
For the toy regression problem with fixed training-set size:
In the particular toy experiment, the minimum occurs at four hidden units / linear regions.
That number belongs to the toy setup, not to neural networks in general.
Squared bias and variance, averaged over the input range, against capacity, for training sets of 15 points; each capacity is fitted to the same 200 training sets. The fixed noise term would add the same offset at every capacity, so it does not move the minimum.
The classical bias–variance trade-off picture from the toy experiment suggests a plausible prediction:
\[ \text{too little capacity} \rightarrow \text{high bias} \rightarrow \text{best region} \rightarrow \text{high variance}. \]
If this picture were universal, once held-out error started rising, more capacity should keep making it worse.
The MNIST-1D capacity sweep uses:
With the original labels, evaluation error continues to decrease even after training error is essentially zero.
The classical U-shaped curve is not a universal description of neural-network generalisation.
With the original labels, evaluation error keeps improving across this sweep.
To make the interpolation threshold easier to expose:
The randomised labels deliberately break the relationship between some training inputs and their assigned targets.
A model cannot infer those assignments from the underlying class structure; to drive training error to zero, it must increasingly fit these sample-specific labels too.
As capacity increases:
This is double descent.
This curve is an observation, not yet an explanation.
We still need to understand how many interpolating solutions can exist and why training reaches some rather than others.
Final training and evaluation error against width, for the original labels (left) and with 15% of the training labels randomised (right); evaluation labels are unchanged in both. The dotted line marks the width at which the training set is first fitted.
A model interpolates a training set when it fits every observed training target exactly under the criterion being discussed.
The interpolation threshold is the effective capacity at which exact fitting first becomes achievable for the training procedure.
The curve is commonly divided into three regions:
| regime | relationship to fitting the training set |
|---|---|
| classical / under-parameterised | model cannot yet fit the data exactly |
| critical | near the point where exact fitting becomes possible |
| modern / over-parameterised | many parameter settings can fit the training data |
The critical point is an effective interpolation threshold; it need not occur exactly when parameter count equals example count.
Once the training examples are already interpolated:
Recall: zero classification error is not zero cross-entropy
A classifier can already classify every training example correctly while cross-entropy still decreases as it assigns more probability to the correct classes.
Here, interpolation refers to satisfying the chosen training-fit criterion, not to every possible loss becoming exactly zero.
The remaining question is which compatible solution the learning system tends to reach.
Inductive bias is the tendency of a learning system to favour some solutions over others when the observed data do not uniquely determine the function.
It can come from:
Interpolation tells us what happens on the training points; inductive bias helps determine what happens between them.
Interpolation constrains what the model does on the observed examples. But a finite dataset occupies only a tiny part of a high-dimensional input space.
MNIST-1D already has 40 input dimensions. Suppose, purely for scale, that each dimension were quantised into 10 bins.
The grid would contain
\[ 10^{40} \]
possible cells.
This is a coverage thought experiment, not a claim that real data uniformly occupy all \(10^{40}\) cells. Real datasets can have substantial structure and much lower intrinsic dimension than their raw input dimension.
With \(10^4\) training examples, that is roughly one observed example for every
\[ 10^{36} \]
cells.
This cell count is only a scale argument, but it shows how sparse \(10^4\) observations are relative to even a coarse grid in 40 dimensions.
At a fixed resolution, the number of regions needed to cover an input space grows exponentially with dimension: \(b\) bins along each of \(D\) dimensions produce \(b^D\) cells.
Consequences include:
The issue is coverage at a chosen resolution, not that every high-dimensional box literally has a larger numerical volume. Low-dimensional diagrams remain useful, but they are only analogies for the geometry of high-dimensional inputs.
Sparse observations leave much of the function underconstrained: many functions can agree on every training point while behaving differently elsewhere.
Increasing capacity enlarges the set of functions that can satisfy those observed constraints.
In the low-dimensional illustration, that larger set includes functions that interpolate the same points more smoothly than a near-threshold fit.
Smoothness is therefore one possible compatible behaviour, not a consequence guaranteed by sparsity or capacity. A smoother interpolant can generalise better only when that preference matches the underlying task.
Available does not mean selected: capacity enlarges the set of compatible functions, but does not determine which one training reaches.
One noisy training set, fitted at three capacities. Left: the classical optimum, which does not pass through the points. Centre: the first capacity that can pass through all of them. Right: far more than enough, with the smallest-norm fit, which is one of many that interpolate.
With a heavily over-parameterised model, many functions can fit the same observed training targets exactly or nearly exactly:
The observations constrain the fitted values at the training examples; they do not uniquely specify behaviour elsewhere.
Three over-parameterised models that pass exactly through the same training points, so all three have zero training loss. They differ only in how they behave between the points.
Inductive bias is the broad preference for some compatible solutions over others. Regularisation is one way to create such a preference.
Initialisation, optimisation path and stopping time can all affect which interpolating solution is reached. Exactly why particular training systems favour particular solutions is an empirical and theoretical question, not a universal guarantee of smoothness.
The experiments establish that evaluation error can improve again after the interpolation threshold.
They do not establish that:
The observed curve also depends on dataset and label noise, architecture, loss, optimiser, regularisation and training duration. A related pattern, epoch-wise double descent, can appear when training duration changes while architecture stays fixed.
Suppose we train 20 candidate systems. We now need data to answer two different questions:
If the same held-out results influence the choice and are then reported as untouched evidence, the second answer is no longer independent of the first.
Earlier, we repeatedly inspected held-out curves to understand training behaviour and double descent.
Once a held-out set influences decisions — even informally — it is part of the development and evaluation loop. It should not also be treated as untouched final evidence for the selected model.
For a final performance estimate, reserve a separate test set until the model, hyperparameters and reporting choices are fixed.
Parameters \(\params\) are learned inside one training run:
Hyperparameters \(\lambda\) configure the model or learning procedure around training runs:
Training chooses \(\params\); model selection chooses \(\lambda\).
A tempting workflow is:
Step 3 uses information from the test set to choose the model. The reported test score is therefore no longer an untouched estimate of performance after selection.
The test set has become part of the model-selection procedure, so it can no longer serve as untouched evidence about the selected system.
| split | used to choose | access pattern |
|---|---|---|
| training | model parameters | repeatedly during optimisation |
| validation | hyperparameters / model choice | repeatedly during development |
| test | final performance estimate | after development choices are fixed; results must not feed back into selection |
The distinction is about information flow, not the filename attached to a dataset.
For each candidate hyperparameter setting \(\lambda\):
\[ \lambda \longrightarrow \text{train on training set} \longrightarrow \text{validation score}. \]
Choose
\[ \lambda^* = \argmin_{\lambda} \loss_{\mathrm{val}}(\lambda) \]
for a loss metric, or the corresponding \(\arg\max\) for a score.
Reminder: argmin
\(\argmin\) returns the setting \(\lambda\) that gives the smallest validation loss; \(\min\) would return the smallest loss value itself.
Only after \(\lambda^*\) is fixed do we evaluate the selected system on the test set.
The validation set is used repeatedly during model selection.
With enough candidate configurations and enough adaptive decisions, some choices can look good partly because they suit quirks of that validation sample.
This is the same generalisation problem at a second level:
The untouched test set estimates performance after both levels of selection.
A fixed train/validation/test split with few examples creates tension:
\(K\)-fold cross-validation reuses the training/validation portion more efficiently while keeping the final test set separate.
Partition the available development data into \(K\) disjoint folds.
For each candidate hyperparameter setting:
After choosing \(\lambda^*\) from this cross-validation evidence:
For example, \(K=5\) gives every development example one turn in validation and four turns in training.
Five-fold cross-validation within the development data. Each row is one training run: four folds train and the fifth validates, and the validation fold moves along. The averaged validation score chooses the hyperparameters; the test set sits apart and is used once, after that choice.
Once validation gives us a way to compare candidate settings, a new problem remains:
Which hyperparameter settings should we spend computation evaluating?
Compared with gradient-based parameter learning, hyperparameter search is awkward because:
The width of layer 10 is only defined for architectures with at least 10 layers. The search space can therefore contain conditional choices rather than forming one simple rectangular grid.
Three useful families are:
The search strategy changes how candidates are explored, not the need for clean validation evidence and a final untouched test set.
A test set estimates performance for data distributed like that test set.
If deployment data follow a different distribution, a perfectly untouched test set can still give a misleading estimate of real-world performance.
Evaluation therefore asks two separate questions:
Even a representative test set is a snapshot.
If the deployed data distribution changes over time:
A change in deployment statistics is a form of distribution shift or drift.
Imagine a vision model that classifies manufactured parts as defective or acceptable.
These examples are deliberately idealised so that one type of change is isolated at a time.
| shift | defining change | held stable in the idealised definition |
|---|---|---|
| covariate shift | \(p(x)\) changes | \(p(y\mid x)\) remains stable |
| label / prior shift | \(p(y)\) changes | \(p(x\mid y)\) remains stable |
| concept shift | \(p(y\mid x)\) changes | no assumption that the old input–output relationship remains valid |
Real deployments can contain mixtures of these shifts. The categories are useful because they point to different diagnostics and possible responses.
A test result supports a statement of the form:
this selected model achieved this measured performance on this held-out sample from this distribution
After deployment, ask whether:
Report the performance number together with the held-out sample and distribution it is intended to represent.
Use the ideas from the session as diagnostic questions:
A single performance number cannot answer these questions by itself.
At a fixed input \(x\),
\[ \expectsub{\set{D},y}{(\model[{\params[\set{D}]}]{x}-y[x])^2} = \underbrace{ \expectsub{\set{D}}{(\model[{\params[\set{D}]}]{x}-f_\mu[x])^2} }_{\text{variance}} + \underbrace{ (f_\mu[x]-\mu[x])^2 }_{\text{squared bias}} + \underbrace{\sigma^2[x]}_{\text{noise}}. \]
Read it as three questions:
Classical regime
Over-parameterised regime
Double descent describes the non-monotonic capacity curve in which held-out error can fall again beyond the interpolation threshold.
The test set is protected because we want one sample that did not participate in deciding what system to report.
An untouched test estimate can become stale when the deployment distribution changes.
A deployed model therefore needs both initial evaluation and ongoing monitoring.