Cross Validation
Advanced 16 min read Cross Validation

Cross Validation for Time Series

Validation that respects the arrow of time

Time ordered data can't be shuffled: the future must never seed the past. TimeSeriesSplit, expanding windows and blocked splits evaluate forecasting honestly while still 'reusing' data for tuning.

TimeSeriesSplitexpanding windowrolling originforecast validationbacktest
Before we start

What you will learn

  • Explain why k-fold shuffling is invalid for time series
  • Use expanding-window splits for honest forecasting
  • Handle lags and feature look-ahead in splits
Introduction

What is this?

Time-series CV runs training on the past and validation strictly on the future. The classic design is the expanding window: train on [t0, t1), validate on [t1, t2); then train on [t0, t2), validate on [t2, t3), and so on — backtesting several future slices. Because every validation slice is chronologically after its training data, the evaluation measures what real forecasting faces: predicting the unknown future with only the past.

Motivation

Why do you need it?

  • Shuffled k-fold leaks tomorrow into the training of today, inflating scores that dissolve live.
  • Drift is the norm in product metrics — validation must sample several horizons, not one.
  • Expanding windows let small datasets reuse data without breaking chronology.
  • Regulators and stakeholders need 'how would this have forecasted last quarter?' not 'how would it fit the past generally?'.
Think about it

Mental model

Imagine

A trader backtesting a strategy

Think of

Rolling-origin forecast evaluation

A strategy is only trustworthy if you replay history from the past forward — never look ahead. Forecasting CV is exactly that: refit on the past, predict the next unseen slices, roll forward.

Mechanics

How it works

  • Order rows by time and split the timeline into train/validation boundaries.
  • TimeSeriesSplit: n_splits expanding training windows with fixed or growing test widths.
  • Each split: train on history up to boundary, validate on the following window — never the reverse.
  • Fit any lags/rolling features on training history only, so their statistics are past-only at validation.
  • Average validation scores across horizons → a forecast-backtest estimate of generalization.

Expanding training windows, future-only validation.

Split 1
Split 2
Split 3
Average
Real world

In production

  • A demand planner validates a forecast model on the last 6 weeks rolling origin: retrain weekly, predict the next week, stack errors.
  • A churn team uses time-based splits because viral waves make historical patterns shift.
  • An MLOps pipeline reports per-horizon backtest metrics (h+1, h+7, h+30) so freshness targets are explicit.
Guidelines

Best practices

  • Always split by a timestamp, using strictly-future validation windows.
  • Train lag features / rolling windows / scaling on each training slice only.
  • Report per-horizon errors; a model great at h+1 may collapse at h+30.
  • Prefer walk-forward (rolling origin) evaluations for the most realistic coverage.
Watch out

Common mistakes

  • Shuffling the time column and 'untimately-valid' leaking day-ahead data into training.
  • Fitting rolling means/scalers on the whole series before splitting.
  • Using TimeSeriesSplit without gap: train and validation adjacent, so short-horizon lags bleed across the boundary.
  • Evaluating on a single horizon and concluding the forecast generalizes.
Root cause analysis

Common issues

Error
Time-series CV score better than live forecast
Root cause

Lag/feature computed with look-ahead (statistics from the validation period)

Fix

Recompute features as-of the training boundary only; test by refitting from a strictly past slice.

Error
TimeSeriesSplit with a tiny gap overfits one week
Root cause

Train ends exactly at validation start, so the last-observed pattern dominates

Fix

Add a cooldown gap between train and validate, or use wider validation steps.

When things break

Debugging tips

  • Plot the train/validate timeline per split — visual confirmation beats argument.
  • If validation beats all history for 'no reason', check lag features computed on data after the boundary.
  • Compute the trivial last-value or seasonal-naive baseline in the same splits; the model must beat it.
  • Compare h+1 vs h+7 curves: divergence reveals where the model runs out of signal.
Interviews

Interview checkpoint

Practice

Hands-on lab

Backtest a Forecast With Expanding Windows
35 min · advanced
In progress
Objectives
  • Build expanding-window splits by hand
  • Fit and evaluate a small rolling-window forecast per horizon
  • Compare against a naive (last-value) baseline honestly

Backtest a Forecast With Expanding Windows

35 min · advanced

0/4 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

The key property of time-series cross validation is:

2

Cross-validating a forecast with shuffled folds gives an honest estimate.

Go deeper

Official documentation