Model Evaluation
Advanced 15 min read Model Evaluation

Evaluation Leakage and Validation Hygiene

Why your AUC is 0.99 in the lab and 0.6 in production

Leakage makes evaluation numbers lie: the test set echoes the training signal. Target leakage, row leakage and preprocessing leakage inflate scores that collapse in production. Clean validation is a discipline, not a setting.

data leakagetarget leakagepreprocessing leakagedata contaminationvalidated metrics
Before we start

What you will learn

  • Recognize the three leakage types: target, row, and preprocessing
  • Keep preprocessing inside cross-validation folds
  • Audit a pipeline for contamination before trusting any number
Introduction

What is this?

Leakage is any path that lets the model (or its evaluation) see information it shouldn't at prediction time. Target leakage hides the answer in a feature (e.g., an 'is_refund' flag predicting churn); row leakage duplicates or co-splits records that came from the same entity; preprocessing leakage fits scalers/encoders/imputers on the whole dataset before splitting. All three inflate evaluation and collapse on genuinely unseen data.

Motivation

Why do you need it?

  • Leakage is the #1 cause of 'great offline, dead in prod' ML failures.
  • It is silent — the code 'works', the metrics look excellent, no error is raised.
  • Fixing leaked metrics retroactively shakes the confidence of every downstream decision made on them.
  • Prevention is cheap once you know the three patterns; debugging contaminated pipelines is expensive.
Think about it

Mental model

Imagine

An exam with the answer key photocopied into the study guide

Think of

A leaked model

Students (the model) ace the exam (test set) because the answers were visible during study, and nobody learns the material — exactly what happens when a pipeline leaks future or label information.

Mechanics

How it works

  • Target leakage: a feature that is only known after the label occurs (a duplicate/derivative of y) sneaks into training.
  • Row leakage: group-corrrelated rows (same user, same image) are split across train and test, so the model 'recognizes the person'.
  • Preprocessing leakage: fit_transform on the full dataset (scaler, encoder, imputer, target encoder) bakes test statistics into training.
  • The leaking fitter runs before the split in a pipeline, so even correct CV code evaluates on contaminated folds.
  • Symptoms: absurd AUC (>0.98) on hard problems, instant test-set overfitting, and monotonic score gaps train-vs-prod.

Three leakage channels all feed evaluation, not just training.

Target leakage
Row leakage
Preprocessing leakage
Inflated metric
Fix
Real world

In production

  • A recommendation team splits by user ID so the same user's actions never straddle train and test.
  • A forecasting team uses only past data for training and strictly future data for validation — any lag feature is shifted correctly.
  • A feature store ships with per-row 'as-of' timestamps so features are joined at prediction time, not at training time.
Guidelines

Best practices

  • Define the 'prediction time view' of every feature — what was knowable at that instant — and build features accordingly.
  • Split groups (user, item, session) rather than raw rows when entities repeat.
  • Put ALL preprocessing inside a single Pipeline whose fit happens per-fold.
  • Audit: sample a few features that look predictive and check 'could I know this at inference?'
Watch out

Common mistakes

  • Calling train_test_split after StandardScaler fit_transform on the whole set — scaler leaks set statistics.
  • Adding 'days_since_last_purchase' computed with the target date rather than the prediction time.
  • Deduplicating images/rows after splitting, so duplicates cross the boundary.
  • Using validation metrics to pick the final model, then 'confirming' on validation because the test set was consumed.
Root cause analysis

Common issues

Error
AUC 0.99 in CV, 0.65 in A/B test
Root cause

Leakage somewhere in the pipeline (preprocessing, target copies, group split)

Fix

Audit each preprocessing step for fit-before-split and each feature for knowability at prediction time.

Error
Model 'predicts the future' — high score on next week despite no signal
Root cause

Lag features shifted incorrectly or target used at feature build

Fix

Rebuild features as-of each prediction timestamp and re-split strictly by time.

When things break

Debugging tips

  • If any single feature has an absurd importance/permutation spike, test it for label resemblance.
  • Check for duplicate row hashes across the split boundary.
  • Fit the pipeline on train only, then transform test — compare metrics to the 'leaky' run.
  • Add a leakage probe: a dummy feature equal to the label (should spike) confirms your audit works, then remove it.
Interviews

Interview checkpoint

Test yourself

Quick quiz

0/2
1

Which is the strongest early warning sign of leakage?

2

Fitting StandardScaler once on the full dataset, then splitting, is safe.

Go deeper

Official documentation