Skip to main content
If you train the model on the same tasks you test it on, the score goes up and means nothing. It is handing out the exam a week early. So before any training, you split the rows. One part trains. The other part is locked away, and the only number you ever report comes from it.

The mechanism

The locked part is the held-out set. Three rules for it.
  1. Never train on it.
  2. Never use it to pick between models while you are still building. Every peek makes it a little less held out.
  3. Measure before and after on it, and nowhere else.
Simulated asks repeat, and production traffic repeats too, so a training row can be a near copy of a test row without anyone meaning it to. The check for that is decontamination: compare every training row’s prompt against every test row’s, and drop the training row when they overlap. The library counts shared runs of eight words and drops a row when 80% of its runs also appear in a test row.

Run it

The setup is lesson 2’s run. The split here is by position, which is fine for a demo. For real rows, split by task so all four tries of an ask land on the same side.
One planted copy, one row dropped. On a real set the count is rarely zero, and every row it drops is a row that would have made the after score lie.
Public benchmarks have the same problem at scale: their questions are on the internet, so they are in the pretraining data. That is one reason a test built from your own traffic, checked for overlap, says more about your agent than a leaderboard does.

Where it comes from

  1. Lambert, N. Reinforcement Learning from Human Feedback. arXiv:2504.12501, 2025. Chapter Evaluation: contamination, and why held-out sets decay.
  2. Miller, E. Adding Error Bars to Evals. arXiv:2411.00640, 2024. The before-and-after on the same questions is a paired test.

Next

Train on what the model gets right sometimes: which of the training rows are worth a gradient.
Last modified on September 19, 2026