ML & Data Foundations · 90 minutes
Explain train, validation, and test splits
Explain what training, validation, and test splits are each for, then repair a fictional marketplace's evaluation plan by choosing a split that matches how its model will be used.
Conceptual scenario
1.5 h
Used in interview rounds:
Technical Screen (Easy)Overview
Every model evaluation depends on keeping some data away from the decisions it judges. This level teaches what the training, validation, and test splits are each for, how to choose a split from the way a model will be used, and what a test score can and cannot claim. You practice on a fictional furniture marketplace's sell-within-14-days model.
Study time: 90 minutes
Interview format: Conceptual screen with a split-selection exercise
By the end you can
- Explain what the training, validation, and test splits are each for, and which decisions each one may inform
- Explain why a test set stops giving an unbiased estimate once it informs any decision, and why every preprocessing step is fitted on training data only
- Choose a random, stratified, grouped, or time-based split from how the model will be used, and handle rows whose label is not final yet
- Use k-fold cross-validation when data is small, and read the average and spread of the fold scores
- State what a single test score does and does not establish
Prerequisites
Helpful background: Basic fractions and averages, and what a classifier is.
This topic covers data splits, leakage, misleading metrics, and evaluation over time for any model. Evaluation & Observability covers evaluation specific to LLM applications.
Why hold data out
A model scored on the rows it was fitted on can score well by memorizing them (overfitting), and that score says little about new rows. So an evaluation holds some rows out: the model is never fitted on them, and they stand in for the data it will meet in use. They do that job only if they resemble that data.
Three splits, three jobs
Most evaluations divide the labeled rows into three disjoint splits, each with one job.
| Split | Job | What may use it |
|---|---|---|
| Training | Fit | Model parameters and every preprocessing step: a scaler's mean and spread, imputation values, a vocabulary |
| Validation | Choose | Comparing models, features, and settings (hyperparameters), early stopping, and the decision threshold |
| Test | Estimate once | Only the final score, after the model, preprocessing, and threshold are frozen |
The option that wins many comparisons on validation carries an optimistic validation score. The test split gives a score that no choice has touched.
Proportions vary (The Elements of Statistical Learning calls 50/25/25 typical); each split must be large enough for the decisions made on it. Teams often refit the chosen setup on training plus validation before the single test run.
Keep the test set untouched
Any choice made by looking at a test score, such as which model to keep, which threshold to use, or "one more try", makes that score optimistic. The Elements of Statistical Learning says to keep the test set "in a vault" until the end: choosing a model by its test error underestimates the true error.
Illustration (constructed numbers). Five models would each score 0.80 on new data. Chance gives them test scores of 0.78, 0.79, 0.80, 0.81, and 0.83. Keeping the best reports 0.83, 0.03 above what the chosen model will score on new data.
Google's Machine Learning Crash Course notes that test sets "wear out" with repeated use. Once one has informed a decision, treat it as development data and get a fresh test set, such as newly labeled rows.
Leakage is the reason
These rules exist because of data leakage: using information that would not be available at prediction time to build the model (scikit-learn's definition), which makes offline scores look better than production will.
One example is a scaler whose mean and spread are computed over all rows, test rows included. Split first, fit each preprocessing step on the training split only, and apply the fitted step unchanged to validation and test rows. A pipeline, such as scikit-learn's Pipeline, does this, even inside cross-validation.
The Medium question in this topic covers other forms of leakage and how to audit for them.
Choose the split from how the model will be used
Most libraries split rows at random by default. Start instead from one question: when the model is used, what will be new to it?
| Situation | Split |
|---|---|
| Independent rows from a stable population | Random rows |
| A rare class or a small dataset | Stratified by label, so every split keeps the class mix |
| Several related rows per entity (such as many orders from one customer), and the model must work for entities it has never seen | Grouped: every row of an entity goes to one split |
| The model predicts future events, and behavior changes with time or season | Time-based: earlier rows to fit, later rows to evaluate |
The choices can combine. scikit-learn's StratifiedKFold, GroupKFold, and TimeSeriesSplit are examples of the last three.
Separately, an overall score can hide a subgroup the model handles badly. Also report the score for each subgroup that matters as a slice, such as entities absent from training, with its row count.
Time-based splits and label windows
For a model that predicts future events, fit on earlier data, validate on later data, and test on the latest. Google's Rules of Machine Learning (Rule #33) recommends measuring on data gathered after the training data, because that better reflects production; shuffling trains on the future and scores on the past. Let training cover a full seasonal cycle when you can, since a test period covers only its own season.
Some labels take time to become final. A label such as "repaid within 30 days" is unknown until the row's window closes: leave such rows out, and never count them as negatives.
A row near the end of the training period gets its label from events in the next period. Leave a gap at least as long as the label window before the later period starts (TimeSeriesSplit has a gap parameter). The gap applies to every row the final model is fitted on, including rows added in a refit. The Medium question checks this boundary.
Cross-validation when data is small
With little data, one validation split is noisy. k-fold cross-validation divides the development data (everything except the test set) into k folds, then fits on k minus 1 and validates on the remaining fold, k times, so every development row is used for validation once. Report the average of the k scores and look at their spread.
The test set is still held out and scored once (in scikit-learn's guide, cross-validation replaces the validation set, not the test set). Variants: stratified, grouped, and time-ordered folds, where training folds always come before the validation fold. The cost is k fits instead of one.
Worked example: five folds, two settings
Worked example
Suppose a secondhand-furniture marketplace's trust team builds a classifier that flags listing descriptions mentioning damage. Staff labeled 600 descriptions; 180 (30%) mention damage. The team set aside a stratified test set of 100 descriptions (30 mention damage), then ran stratified 5-fold cross-validation on the other 500 to compare settings A and B: each fold fits on 400 descriptions and validates on 100 (30 mention damage). The score is accuracy, chosen for simple arithmetic (the Medium question shows when accuracy misleads). All figures are synthetic.
| Fold | Setting A | Setting B |
|---|---|---|
| 1 | 0.82 | 0.86 |
| 2 | 0.79 | 0.75 |
| 3 | 0.85 | 0.88 |
| 4 | 0.80 | 0.77 |
| 5 | 0.84 | 0.79 |
| Average | 0.82 | 0.81 |
A's average is (0.82 + 0.79 + 0.85 + 0.80 + 0.84) / 5 = 4.10 / 5 = 0.82; B's is (0.86 + 0.75 + 0.88 + 0.77 + 0.79) / 5 = 4.05 / 5 = 0.81. With fold 1 alone as the validation split, the team would pick B (0.86 against 0.82); with fold 2 alone, A (0.79 against 0.75). A's lead of 0.01 is much smaller than either setting's range across folds (A 0.79 to 0.85, a range of 0.06; B 0.75 to 0.88, a range of 0.13), so the folds do not clearly separate them.
A reasonable team picks A for its steadier scores, or treats the two as tied and keeps the simpler one, then refits the choice on all 500 descriptions and scores the 100 test descriptions once. Always predicting "no damage" would score 0.70; both settings beat that.
What a test score does and does not show
A test score estimates how the frozen model and threshold perform on data like the test split, drawn the way that split was drawn. It is coarse and noisy: one row moves an accuracy-style score by 1/n, so 0.5 percentage points on 200 rows (1/200 = 0.005) and 0.01 percentage points on 10,000 rows (1/10,000 = 0.0001), and chance alone moves it by many more rows than one. Report each slice score with its row count.
A test score does not show:
- Performance in periods, seasons, or populations the test split lacks.
- Performance after the data changes: monitor after launch (the Hard question covers drift).
- Whether the feature helps users: that takes an online experiment (see AI Product Experimentation).
- Anything at all once the test set has informed a decision.
Exercise: pick the split for each task
Use "Three splits, three jobs" and "Choose the split from how the model will be used". Each row is a separate task at the same furniture marketplace.
Predict the outcome
Pick the split for each task
For each task, name the split you would use (its role, unit, or order) and give a one-line reason, then reveal the answers.
| Task or dataset | How the model will be used | Split to use | Reason |
|---|---|---|---|
| R1. Compute the mean and spread used to rescale asking price and photo count (a scaler) | A model that scores new listings for a manual-review queue | ? | ? |
| R2. Choose the score threshold above which a listing goes to manual review | The same review-queue model | ? | ? |
| R3. Produce the one number quoted in the launch review | The same review-queue model | ? | ? |
| R4. One dealer posted 40 listings with near-identical photos and wording, and many other sellers posted several listings each | A check that runs only on a seller's first listings during sign-up, so every seller it scores is new to it | ? | ? |
| R5. 18 months of new-listing counts per city per month, with a peak every late summer | Forecast next month's new listings per city to plan moderation staff | ? | ? |
| R6. 1,000 staff-labeled photos, one per listing and each from a different seller; 100 show only part of the item | A classifier that asks sellers to retake photos showing only part of the item; the team must choose between two settings | ? | ? |
Scenario: a sell-within-14-days model
Worked example
Scenario (fictional). Suppose a secondhand-furniture marketplace wants a model that scores each listing at the moment it is posted and predicts whether it will sell within 14 days. When the predicted chance is below a threshold, the listing form shows the seller a pricing tip. The model uses details known at posting time, such as category, asking price, photo count, and city. The team plans to launch the tip in August 2026, the start of the late-summer peak. Every figure below is synthetic.
Label rule. A listing's label is 1 if it sold within the 14 days after the day it was posted, and 0 otherwise. The label becomes final at the end of the 14th day after posting. The data snapshot was taken at the end of 14 July 2026.
| Listings posted | Listings | Sold within 14 days |
|---|---|---|
| 2025 Q1 (January to March) | 7,200 | 2,160 (30%) |
| 2025 Q2 (April to June) | 9,000 | 3,240 (36%) |
| 2025 Q3 (July to September) | 12,600 | 5,670 (45%) |
| 2025 Q4 (October to December) | 8,400 | 2,352 (28%) |
| 2026 Q1 (January to March) | 7,800 | 2,262 (29%) |
| 2026 Q2 (April to June) | 9,000 | 3,060 (34%) |
| 1 to 14 July 2026 | 1,900 | Not final at the snapshot |
Sellers. About 6,000 sellers posted the 54,000 listings from 2025 Q1 to 2026 Q2. 150 dealer accounts posted 40 or more listings each, 13,500 listings in total. Of the 9,000 listings posted in 2026 Q2, 6,300 came from sellers who had posted before April 2026, and 2,700 from sellers whose first listing was in 2026 Q2.
The product manager asks: "Will the tip work for first-time sellers too?"
A teammate's draft evaluation plan
- Use all 55,900 listings, counting the 1,900 July listings as not sold.
- Fit the scaler for asking price and photo count on all 55,900 listings.
- Shuffle the listings and split them 80/20: 44,720 to train and 11,180 to test.
- Train three candidate models, keep the one with the best test score, then move the tip threshold until that test score is highest.
- Report that test score in the launch review as the score the model will reach all year.
Completion checklist
- I can name the decisions each split may inform.
- I can explain why choosing anything on the test split makes its score optimistic.
- I can choose the split order and unit from how the model will be used.
- I can average fold scores and say what their spread shows.
- I can say what a single test score does not establish.
Sources
- scikit-learn User Guide: Cross-validation, evaluating estimator performance Explains holding out a validation set so that tuning does not let knowledge of the test set leak into the model, keeping a test set for final evaluation when using cross-validation, averaging k-fold scores, and the stratified, grouped (GroupKFold), and time-series (TimeSeriesSplit) iterators.
- scikit-learn: Common pitfalls and recommended practices Defines data leakage as using information that would not be available at prediction time, says test data should never be used to make choices about the model, and shows fitting preprocessing on the training subset only, with pipelines.
- Google Machine Learning Crash Course: Datasets, dividing the original dataset Describes the training, validation, and test sets and their roles, and notes that validation and test sets wear out with repeated use and can be refreshed with new data.
- Google: Rules of Machine Learning Rule #33: measure a model on data gathered after the data it was trained on, because that better reflects what the system will do in production.
- The Elements of Statistical Learning, 2nd edition (Hastie, Tibshirani, Friedman) Official free edition. Section 7.2 gives the training, validation, and test roles, calls 50/25/25 a typical split, says to keep the test set in a vault, and warns that choosing a model by test error underestimates the true error. Section 7.10 covers K-fold cross-validation and the wrong and right way to do it.
- scikit-learn API: TimeSeriesSplit Warns that other cross-validation methods would train on future data and evaluate on past data when samples are ordered in time, and documents the gap parameter that excludes samples between each training set and its test set.
The furniture marketplace, listings, sellers, draft plan, fold scores, exercise datasets, and rubric are original synthetic teaching material about a fictional application; no real model or dataset was evaluated. Study times and readiness thresholds are editorial estimates. Library details are as of November 2026.
Related on CodeSnatch
Lessons, problems, and articles that build the skills this question uses.
AI Engineering
Reuses train, validation, and test roles and a grouped split when deciding whether fine-tuning helped.
Practice problem
Code a check that keeps every group of related rows, and every repeated example, inside one split.
Behavioral Interview
Helps you tell a product manager what a score can claim without simplifying it into a promise.
AI Engineering
Shows how an online test with a fair baseline answers what an offline test score cannot: user benefit.
Practice problem
Practice reporting per-slice results with their own counts, so a small subgroup is read with care.
Practice the interview question
Answer it in your own words before you look at the reference answer.
