You would never grade your own exam using the answer key you memorised it from — of course you'd score perfectly, and the score would tell you nothing about how well you actually understand the material. Machine learning has exactly the same trap, and it is one of the most common and most damaging mistakes in applied ML: judging a model using the same data it learned from, or — almost as bad — quietly reusing your "final test" so many times while tweaking the model that it stops being a fair test at all.
We already split data into
The three piles aren't just labels — they define a strict order of operations. First, train several
candidate models (or the same model with several different settings) purely on the training set.
Next, run every candidate on the validation set and compare their scores; this is where you pick the
winner — the best value of
Notice what this buys you: the validation set is allowed to shape your decisions precisely because you already know you'll double-check the final choice somewhere it has never been used to make decisions. Skip the test set, or use it more than once, and that safety net disappears.
The exam analogy actually maps onto the three sets almost perfectly. The training set is like the textbook and worked examples you study from — you're allowed to look at the answers as many times as you like while you're still learning. The validation set is like a practice exam: you take it, see your score, and use that feedback to decide what to restudy or which study method to switch to, over and over, right up until you feel ready. The test set is the real, final exam — sat exactly once, under conditions where you can no longer go back and "just check one more practice question" before submitting. Treating a practice exam as though it were the real one, over and over, tells you nothing honest about how you'd do on the day that actually counts.
Worked example: suppose you're deciding how strong to make a
Slide to change how much data goes to training; the rest is shared evenly between validation and test. A typical split for a modestly sized dataset is something like 60/20/20 or 70/15/15 — more training data usually means a better-fitted model, but you still need enough held back to tune confidently and to judge honestly at the end.
Put real numbers on it: a dataset of 10,000 labelled photos split 70/15/15 gives you 7,000 photos to train on, 1,500 to validate candidate models with, and 1,500 sealed away for the single final test. Shrink the dataset to just 1,000 photos with the same proportions, and the test set shrinks to 150 — still useful, but its accuracy estimate wobbles a lot more from one random split to the next, simply because there are fewer examples to average over.
The right ratio depends on how much data you have. With millions of examples, even a tiny slice — say 2% validation and 2% test — still leaves tens of thousands of examples for tuning and judging, so a lopsided 96/2/2 split is common and efficient, leaving the vast majority for training. With only a few hundred examples, the opposite problem appears: carve off 20% for test and you're judging your final model on a few dozen examples, which is noisy no matter how careful you are. That is exactly the situation cross-validation, described next, is built to help with.
Imagine you train a model, check its accuracy on your "test" set, don't like the number, go back and adjust a hyperparameter, and check the test set again. It feels harmless — you didn't touch the model's training data. But you did use information from the test set to steer a decision, and that is exactly what "leakage" means. Do this enough times and the test set has quietly become just another validation set — except you're still reporting its score as if it were an untouched, honest final number. It isn't anymore. Your reported accuracy will be optimistic, sometimes wildly so, and it will not hold up on genuinely new data. The rule has no exceptions: touch the test set exactly once, after every other decision has already been made.
Concretely: suppose a model genuinely performs at 75% accuracy on data it has never seen. If you tune twenty different settings by repeatedly checking the "test" set and keep whichever one scores highest on that same test set, you're no longer measuring the model — you're measuring the best of twenty rolls of the dice against that one particular batch of examples. It's entirely plausible to walk away reporting 85% or 90%, when the honest number, measured on truly fresh data, is still 75%. The gap doesn't show up until the model meets real data in production and quietly underperforms every claim made about it.
Size matters too, in the other direction. A test set that is too small gives a final verdict that bounces around a lot depending on which exact examples happened to land in it — a handful of unlucky or lucky cases can swing the reported accuracy by several percentage points. A trustworthy final number needs both an untouched test set and enough examples in it to be stable.
With little data, carving off a single validation set feels wasteful — every example set aside for
validation is one fewer example the model gets to learn from — and the resulting score can be noisy,
since it depends on which particular examples happened to land in that one slice.
k-fold cross-validation fixes both problems at once: split the training data into
Worked example: say you've already carved off a test set, leaving 1,000 examples for
training-plus-validation. With
Real machine-learning competitions enforce the train/validation/test split more ruthlessly than any classroom ever could. On a platform like Kaggle, competitors download a training set and can check their own validation scores as often as they like — but the true test set's labels are withheld entirely, often on a server nobody can see, right up until the closing bell. You submit predictions, not code that could peek, and your leaderboard score is computed on data you genuinely never touched. That is the whole design: it makes test-set leakage structurally impossible, not just against the rules.
Outside of competitions, the discipline sometimes slips. A number of published research results have later turned out to be less impressive than they first looked, because — often by an honest accident during data preparation — a handful of test examples ended up duplicated into the training set, or a preprocessing step was fit using statistics from the whole dataset, test set included, before the split was made. The lesson is the same one this page keeps returning to: the moment test data influences any decision, however indirectly, the final number it produces can no longer be trusted.
One especially sneaky version of this mistake is easy to miss: fitting a preprocessing step — like scaling features to a common range, or filling in missing values with the dataset's average — using all the data, including the test rows, before splitting. Even though the model itself never sees a test label during training, the scaling numbers it depends on were quietly computed with the test set's help. The fix is simple once you know to look for it: always fit preprocessing steps on the training set alone, then apply those same fitted numbers — unchanged — to the validation and test sets.