Cross-Validation and Reliable Evaluation

LESSON

Machine Learning Foundations

014 30 min intermediate

Cross-Validation and Reliable Evaluation

By the end of this lesson, you will be able to...

  • design an evaluation split from the moment and population for which a prediction will actually be used;

  • trace how cross-validation refits a complete feature-and-model pipeline across several development folds;

  • interpret fold scores as evidence for a choice, while keeping a final test set untouched until that choice is fixed.

Idea in one sentence: Cross-validation is useful when every fold represents a plausible rehearsal of the real prediction decision, not merely when every row has appeared in a fold.

Core Insight

Consider the claims team from the previous lesson. At 09:00 each day, it scores new claims to decide which ones need manual review. The team has built a time-bounded feature pipeline and wants to choose between logistic regression and gradient boosting.

The tempting plan is simple: shuffle all historical claim rows, make five folds, and choose the largest average score. It sounds careful because every row will be validation data once.

But the product promise is not “predict a randomly hidden row from any date.” It is “make a decision at 09:00 using only what was known then.” A random fold can place an October claim in training while asking the model to validate a January claim. It can also let a learned scaler or category encoder see validation-fold values if the pipeline is fitted before the folds are made.

Cross-validation is therefore an evaluation design, not a ritual. It asks a repeated question: if we had stopped at an earlier point and built the whole pipeline from the information available then, how well would it have served the next period?

The Promise We Need to Keep

The team writes its prediction contract before selecting a splitter:

Contract question Answer for this model
What is predicted? whether a newly submitted claim needs manual review
When is it predicted? each weekday at 09:00
What information is allowed? claim fields and histories available before that run
What population will receive scores? future claims, often from claimants already seen before
What decision metric matters? recall at a review capacity the team can afford

This table changes the design question. The team is not primarily trying to distribute rows evenly. It is trying to make validation look like a past version of the decision it will make later.

Plain meaning: validation should hide information that would not have existed when the deployed model made its prediction.

In this scenario: a claim scored in July must not be evaluated by a pipeline trained with August or October data.

Technical name: this is an out-of-time evaluation design. A chronological cross-validation scheme repeatedly trains on an earlier window and validates on the next window.

The Naive Design

Suppose the team has claims from January through December. Its first design does this:

shuffle all rows
-> make five random folds
-> fit features and model once per fold
-> average the five validation scores

This design can be reasonable when examples are effectively independent and identically distributed: each row comes from the same stable process and has no meaningful memory of time or membership. That condition sometimes holds well enough for a small tabular task. It is not a default truth about operational data.

The initial design also sounds fair because a row is never in both training and validation in the same fold. Yet it can still create an impossible rehearsal. A later fraud pattern, policy change, category, or claimant history may influence training for an earlier validation date. The score can be high because the question was made easier, not because the model will work at 09:00.

The evidence is in the timeline, not in the score:

random fold
training:    Jan ... Oct  | validation: Jan, Mar, Jul, Sep

real decision
training:    Jan ... Jun  | validation: Jul ... Aug

The first line lets the training data include information from after some validation claims. The second preserves the direction of the actual decision.

Why It Breaks

There are three different reasons a familiar splitter may fail. They should not be collapsed into one slogan.

Time dependency. If the model will predict later events from earlier data, training on future rows is leakage. The team needs chronological folds.

Repeated entities. If a model will be deployed for entirely new hospitals, devices, or patients, validation should keep each entity in one side of a fold. Otherwise the model can learn entity-specific patterns and appear to generalize when it only recognizes an already-seen entity.

Class imbalance. If manual-review cases are rare, an ordinary split can create a fold with too few positive cases for a useful recall estimate. Stratification keeps class proportions approximately similar across folds.

These are different pressures, and they can conflict. In the claims team’s actual future-scoring workflow, seeing an existing claimant’s earlier claims in training and their later claim in validation is realistic; the feature contract permits past history. A group-only split that forces every claimant into exactly one side would answer a different question: “can this model generalize to claimants never seen before?” That may be valuable, but it is not automatically the deployment promise.

So far, we have seen that “grouped data” does not automatically mean “use grouped cross-validation.” First name the population the model must serve and the time at which it must serve it. Then choose the split that makes that promise testable.

A Better Boundary: Repeated Past-to-Future Rehearsals

The team reserves November and December as a final test period. Nobody may use it to choose features, models, thresholds, or hyperparameters. It is the last confirmation, not another tuning dashboard.

For development, the team uses January through October in three expanding windows:

Fold Training evidence available Validation period Question being rehearsed
1 January–April May–June Could an April model serve the next two months?
2 January–June July–August Could a June model serve the next two months?
3 January–August September–October Could an August model serve the next two months?

The complete pipeline is rebuilt in each row of this table:

for each fold:
  fit time-bounded feature functions and learned transformers on that fold's training rows
  fit candidate model on those transformed training rows
  apply the unchanged fitted pipeline to the later validation rows
  compute recall at the agreed review capacity

“Rebuilt” does not mean that feature logic changes by fold. The contract remains the same: the 365-day history count ends at the scoring time, missing values follow one named policy, and category encoding learns only from the training portion. What changes is the evidence available to fit data-dependent parts of the pipeline.

This is why cross-validation belongs after feature engineering. A correct feature rule can still leak if it is fitted with all rows before splitting. A pipeline makes the boundary executable: each fold gets its own training-fitted transformer and model.

Read the Evidence, Not Only the Average

Assume these numbers are illustrative. At the fixed review capacity, the team records recall for each validation period:

Candidate May–Jun Jul–Aug Sep–Oct Mean
Logistic regression 0.71 0.70 0.73 0.71
Gradient boosting 0.75 0.64 0.75 0.71

If the team reads only the mean, the candidates are tied. The fold trace tells a more useful story: gradient boosting has larger swings, especially in July–August. That does not prove it is worse. The folds are few, the periods may differ in difficulty, and the values are not a formal confidence interval.

It does create a concrete review question: what changed in July–August? The team can inspect class prevalence, new claim categories, missing-value rates, and the score distribution at the chosen review capacity. Perhaps the boosted model is more sensitive to a shifted representation; perhaps the apparent gap is ordinary sampling variation. The fold scores tell the team where to investigate rather than granting a verdict by arithmetic alone.

Under the stated constraint—a limited review team that values stable recall—the team may prefer logistic regression until the unstable period is understood. That is a situated preference, not a universal claim that simple models are better. If a later analysis shows that boosting’s variation is explained and its later-period recall is reliably higher, the decision can change.

What This Changes in the Development Loop

Cross-validation helps make development choices: select a feature contract, compare model families, tune settings, and choose a threshold. Once the team looks at fold results and changes any of those choices, those results have influenced the design. They are no longer an untouched final exam.

The honest sequence is:

1. Write prediction and split contracts.
2. Reserve a final future test period.
3. Compare complete pipelines with development folds.
4. Record the chosen pipeline and threshold without reading the final test.
5. Refit that fixed pipeline on all development data.
6. Evaluate once on the final test period.

The final test is not magic. A single future period can also be unusual. It is useful because it has not participated in repeated choices. When performance after deployment matters, continued monitoring on later data is still needed; this lesson does not solve distribution shift or decide how frequently to retrain.

Consequences, Trade-offs, and Limits

This design improves the credibility of model comparison because every development score is produced by a plausible past-to-future rehearsal. It costs data and computation: early folds train on less history, several full pipelines must be fitted, and choosing a final holdout leaves fewer rows for development.

It can still fail when the historical periods do not represent the future, the target is measured incorrectly, or the split omits a decisive deployment constraint. A time-aware split does not by itself make the labels fair, the feature contract valid, or the metric aligned with harm.

Three signals reveal a boundary:

Check Your Understanding

Check: A hospital model will be trained on several hospitals and then deployed only at a new hospital. Is it enough to use random stratified folds because the positive rate is preserved?

Think first, then reveal.

Answer: No. Stratification can make class proportions usable, but rows from the same hospital may still appear in training and validation. The deployment promise is generalization to an unseen hospital, so the evaluation must keep hospitals separated as groups. If timing also matters, the team needs a design that respects both constraints.

Check: A claims model predicts future claims for claimants it has already served. Must every claimant be isolated in one fold?

Think first, then reveal.

Answer: Not necessarily. If earlier claims are genuinely available at prediction time and the future deployment includes repeat claimants, training on earlier claims and validating on later claims can be realistic. The important restriction is temporal: no future information may flow backward. A group-only split would test a different, stricter population.

Practice: Review an Evaluation Plan

A retailer wants to predict whether an order will be returned. Data runs from January to October. The model will score orders at checkout; return labels arrive weeks later. The proposed plan shuffles every order, computes target encoding for product category on all rows, runs five-fold cross-validation, and picks the highest average AUC.

Write the smallest correction that makes the plan a credible rehearsal. Name the split, the transformation boundary, and what to keep untouched.

Model answer: Reserve the newest period, such as September–October, as a final test set before choices begin. On January–August, use expanding chronological folds where each validation window follows its training window. Fit target encoding and every other learned transformation only on each fold’s training rows, then apply it to that fold’s later validation orders. If the deployment must generalize to unseen shoppers or stores, add a group constraint; do not add it merely because repeated IDs exist. Choose the model and threshold from development results, record that choice, then evaluate once on the untouched newest period.

Resources

Key Takeaways

PREVIOUS Feature Engineering and Representation NEXT Overfitting, Underfitting, and Regularization