Data leakage identification and prevention

[!definition] What IS Data Leakage?
Data leakage is the use of information in the model training process that would not be available at prediction time in a real-world deployment scenario.
Three main types:
- Target leakage: Features that are influenced by or derived from the target variable itself
- Train-test contamination: Information from the validation/test set influencing training
- Temporal leakage: Future information bleeding into past predictions
WHY These Are Different
- Target leakage = using variables that are causally downstream of what you're predicting
- Train-test contamination = violating the independence assumption between training and validation
- Temporal leakage = violating the temporal ordering of real-world data flow
[!formula] Mathematical Framework of Leakage
Let's derive why leakage breaks the learning process from first principles.
The ML assumption:
We want to minimize expected risk:
But we only have access to training data, so we minimize empirical risk:
Derivation of why leakage breaks this:
With leakage, our features become instead of just .
During training:
WHY this step? The model learns where depends on or unavailable information.
But in production, we only have , not :
The divergence:
This divergence is unbounded when strongly depends on or future information.
Concrete derivation for target leakage:
Suppose feature where is deterministic and $\epsilon is small noise.
The model learns:
WHY? The feature is a near-perfect encoding of the target.
Training error:
But in production, is not available or is computed without knowing :
[!example] Worked Example 1: Credit Card Fraud (Target Leakage)
Scenario: Predicting fraudulent transactions using transaction data.
The Dataset:
transaction_id, amount, merchant, is_fraud, account_balanceafter_dispute
1001, 500, Amazon0, 5000
1002, 2000, Unknown, 1, 3000 ← disputed, money returned
1003, 100, Walmart, 0, 4900
The Leakage: Including account_balance_after_dispute as a feature.
Why it feels right: "Balance changes might indicate fraud patterns!"
Why it's WRONG:
account_balance_after_disputeis calculated AFTER fraud investigation- The fraud label
is_fraudcauses disputes, which cause balance changes - Causal direction:
is_fraud → dispute → account_balance_after_dispute
Step-by-step impact:
Training phase:
# Model sees:
X = [500, 'Amazon', 5000] → y = 0 (no dispute, balance unchanged)
X = [2000, 'Unknown', 3000] → y = 1 (dispute filed, money returned!)WHY this step? The balance column is a near-perfect predictor because it encodes the dispute outcome.
The model learns: "If balance went down by transaction amount, it's fraud!" (99% accuracy)
Production phase:
# Model receives:
X = [1500, 'Shady Site', ???] ← account_balance_after_dispute doesn't exist yet!Accuracy colapses because the feature that gave99% training accuracy is unavailable.
The fix: Only use features available at transaction time:
amount,merchant,time_of_day,location,historical_fraud_rate- Never:
dispute_filed,chargeback_amount,investigation_outcome
[!example] Worked Example 2: Time Series (Temporal Leakage)
Scenario: Predicting daily stock returns.
The Dataset (2024-01-01 to 2024-12-31):
date, open, close, volume, rolling_mean_30d, return_next_day
2024-01-15, 100, 102, 1M, 101.5, 0.02
2024-01-16, 102, 104, 1.2M, 102.0, 0.015
The Leakage: Computing rolling_mean_30d on the entire dataset before splitting.
Step-by-step derivation of the problem:
# WRONG: Global calculation
df['rolling_mean_30d'] = df['close'].rolling(30).mean()
train = df[df['date'] < '2024-07-01'] # First 6 months
test = df[df['date'] >= '2024-07-01'] # Last 6 monthsWHY this is wrong: For a test sample on2024-07-15:
- The
rolling_mean_30duses data from 2024-06-15 to 2024-07-15 - But 2024-06-15 to 2024-06-30 is in the training set!
- Information flows backward: test set → training features
Mathematical formalization:
For test point (where is train/test split):
Feature calculation:
WHY this step? Rolling window looks back30 days from the test point.
This includes: ↑ training data ↑ test data
The model learns spurious correlations between train and test sets.
The correct approach:
# RIGHT: Temporal split FIRST, calculate SECOND
train = df[df['date'] < '2024-07-01']
test = df[df['date'] >= '2024-07-01']
# Calculate rolling mean ONLY on training data up to that point
train['rolling_mean_30d'] = train['close'].rolling(30).mean()
# For test: use only training data for the calculation
for in test.index:
relevant_history = df[(df['date'] < df.loc[i, 'date']) &
(df['date'] >= df.loc[i, 'date'] - timedelta(days=30))]
test.loc[i, 'rolling_mean_30d'] = relevant_history['close'].mean()WHY this step? We simulate the real-world scenario: at prediction time , you only know history up to .
[!example] Worked Example 3: Train-Test Contamination (Scaling Leakage)
Scenario: Predicting house prices with features at different scales.
The Dataset:
house_id, sqft, bedrooms, price
1, 2000, 3000
2, 1500, 2, 250000
.., .., ...
100, 3000, 4, 5000
The Leakage: Fitting the scaler on the entire dataset.
# WRONG approach
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit(X) # X contains both train and test
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y)Why it feels right: "Standardization is just preprocessing, not model fitting!"
Derivation of why it's wrong:
StandardScaler computes:
WHY this step? We're computing population statistics across all data.
Then scales:
If we fit on all data ( = train + test samples):
The contamination: Test set statistics influence training features!
Impact on model:
The model learns on training data where features are scaled using test set information:
In production, new data has different distribution:
Numerical example:
Training houses: sqft = [1000, 1500, 2000], mean = 1500
Test houses: sqft = [3000, 3500, 4000], mean = 3500
Fitting on all:
Training sample (1000 sqft):
WHY this step? The test set's high values pull the mean up, making training samples appear more extreme.
The model learns that "large negative scaled values" predict low prices, but this relationship is artifact of the scaling, not true pattern.
The correct approach:
# RIGHT: Fit on train, transform both
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # Learn stats from train only
X_test_scaled = scaler.transform(X_test) # Apply train stats to testThis simulates production: you'll compute and from historical data, then apply to new samples.
[!mistake] Common Mistakes & Stelmanning
Mistake 1: "Data augmentation can't cause leakage"
Why it feels right: "I'm just creating more training samples, not touching test data!"
The steel-man argument: Data augmentation increases training set size without collecting new data. It seems like a pure preprocessing step.
Why it CAN cause leakage:
# Image classification example
X_train, X_test, y_train, y_test = train_test_split(X, y)
# WRONG: Augment after split, but normalize on augmented data
X_train_augmented = augment(X_train) # Now 10x larger
scaler.fit(X_train_augmented) # Stats influenced by augmentation
X_train_final = scaler.transform(X_train_augmented)
X_test_final = scaler.transform(X_test) # Uses augmented stats!The problem: Augmentation changes the distribution. If you compute statistics (mean, std) on augmented data, you're using a distribution that doesn't exist in production.
Mathematical view:
Augmentation creates where
If you scale using from , but test/production data comes from :
WHY this step? You've created a distribution shift between training and evaluation.
The fix: Compute statistics on original training data, then augment:
scaler.fit(X_train) # Original training distribution
X_train_scaled = scaler.transform(X_train)
X_train_augmented = augment(X_train_scaled) # Augment AFTER scalingMistake 2: "Cross-validation prevents all leakage"
Why it feels right: "CV splits data multiple times, so information can't leak!"
The steel-man: Cross-validation does protect against overfitting to a single train/test split. It's a robust validation strategy.
Why it's INCOMPLETE:
CV protects against train-test contamination within each fold, but NOT against:
- Global preprocessing leakage:
# WRONG: Scale before CV
X_scaled = scaler.fit_transform(X)
cross_val_score(model, X_scaled, y, cv=5) # Each fold uses global stats!WHY wrong? Each fold's validation set influenced the scaling of its training set.
- Temporal leakage in time series:
# WRONG: Random CV on time series
cross_val_score(model, X, y, cv=5) # Random splits violate temporal order!The fix for time series: Use TimeSeriesSplit:
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
# Ensures fold i only uses data before fold i+1Derivation of why random CV fails for time series:
In random CV, fold might have:
- Training
- Validation:
WHY this is wrong? Training on while validating on means using future to predict past!
The model learns:
Mistake 3: "Feature selection can't cause leakage"
Why it feels right: "I'm just choosing relevant features, not using test labels!"
The steel-man: Feature selection improves model performance by removing noise. Seems safe.
Why it DOES cause leakage:
# WRONG: Select features on full dataset
from sklearn.feature_selection import SelectKBest
selector = SelectKBest(k=10)
X_selected = selector.fit(X, y) # Uses ALL y values, including test!
X_train, X_test, y_train, y_test = train_test_split(X_selected, y)The leakage mechanism:
Feature selection computes correlation/mutual information:
WHY this step? We're measuring how much tells us about .
If computed on all data:
The test set labels influence which features are selected for the training set!
Concrete example:
Dataset: 100 samples, 1000 features
- Feature is randomly corelated with (spurious)
- Feature is truly predictive
If we select features using all data, might be selected because it correlates with test labels. The model learns this spurious correlation, but it won't generalize.
The fix:
# RIGHT: Feature selection inside CV
pipe = Pipeline([
('selector', SelectKBest(k=10)),
('model', RandomForestClassifier())
])
cross_val_score(pipe, X, y, cv=5) # Selector refit in each foldSystematic Leakage Detection Framework
Step 1: Causal Graph Analysis
Draw the causal relationships:
[Transaction] → [Fraud Occurs] → [Investigation → [Dispute Filed] → [Balance Change]
↑ OK to use ↑ Target ↗ LEAKED features →
Rule: Only use features that are causally upstream of or independent of the target.
Step 2: Timeline Analysis
For each feature, ask: "When is this value known?"
Prediction time: t
Feature X_j available at: t_j
If t_j > t → TEMPORAL LEAKAGE
Step 3: Validation Distribution Test
Compare feature distributions:
# Check for leakage signal
from scipy.stats import ks_2samp
for col in X_train.columns:
stat, p_value = ks_2samp(X_train[col], X_test[col])
if p_value < 0.05:
print(f"Warning: {col} distributions differ - possible leakage")WHY this works? If preprocessing leaked information, train/test distributions will be artificially similar.
Step 4: Ablation Testing
Remove suspected leaky features and retrain:
If , investigate deeply—one feature shouldn't have that much power unless it's leaking.
[!recall]- The Feynman Explanation
Imagine you're studying for a test, and your friend hands you a study guide. Later you find out that study guide had the actual test questions in it! You did great, but you didn't actually learn the material.
Data leakage is when your AI model gets to "peek at the answers" during training. It happens in three main ways:
-
The answer is in the question: Like if I ask "What's the capital of the country where Paris is?" - the answer (France) is basically in the question. That's target leakage—using information that only exists because of the answer.
-
Studying with tomorrow's newspaper: Imagine studying for a Monday test but you have Tuesday's newspaper. You'd see what happens after Monday! That's temporal leakage—using future information to predict the past.
-
Sharing answers before the test: If your practice tests and real test shared some answers, you'd do great on test day but not actually know the material. That's train-test contamination—mixing training and testing information.
Why it's bad: Your model looks like a genius (99% accuracy!) but fails in the real world because it learned the wrong thing. It's like memorizing test answers vs. understanding concepts.
How to prevent it: Always ask "Would I have this information at prediction time in real life?" If no, don't use it for training!
[!mnemonic] The T.T.T Leakage Check
Target dependency → Does this feature depend on the target? Temporal order → Is this information from the future? Training isolation → Did I fit/compute this on training data only?
Before using ANY feature, check all three T's. If any fails, investigate for leakage.
Memory aid: "Test The Timeline" - trace information flow from feature creation to prediction.
Key Prevention Strategies (80/20 Rule)
These 20% of practices prevent 80% of leakage:
- Pipeline everything - Use
sklearn.pipeline.Pipelineto ensure all preprocessing refit on each CV fold - Split first, preprocess second - ALWAYS split before any statistics/scaling/feature selection
- Temporal awareness - For time series, use
TimeSeriesSplitand never shuffle - Causal reasoning - Draw the causal graph; only use features upstream of the target
- Production simulation - Ask "Would this be available at prediction time?"
Active Recall Practice
Connections
- Train-testvalidation split strategies - Proper splitting prevents contamination
- Cross-validation techniques - CV must respect temporal order and preprocessing isolation
- Feature scaling and normalization - Common source of subtle leakage
- Time series forecasting fundamentals - Temporal leakage is critical here
- Model evaluation metrics - Leakage inflates metrics deceptively
- Pipeline and workflow automation - Pipelines prevent preprocessing leakage
- Causal inference basics - Understanding causality prevents target leakage
- Production model deployment - Train/prod distribution mismatch reveals leakage
#flashcards/ai-ml
What is data leakage? :: Information from outside the training dataset that wouldn't be available at prediction time leaking into the model during training, causing artificially high validation performance that doesn't generalize to production.
What are the three main types of data leakage?
Why does scaling on the full dataset cause leakage? :: The scaler's mean and std are computed using test data, so training features are transformed using test set statistics. This creates an artificial relationship between train and test that won't exist in production where new data has different statistics.
What is target leakage and give an example :: Using features that are causally downstream of or directly influenced by the target variable. Example: using "account_balance_after_dispute" to predict fraud, when disputes only occur AFTER fraud is identified—the feature encodes the target outcome.
What is temporal leakage in time series?
Why is feature selection a potential source of leakage?
How do you prevent preprocessing leakage in cross-validation?
What is the correct order: split then preprocess, or preprocess then split?
Why can't you use train_test_split for time series data?
What is the T.T.T. leakage check mnemonic?
How do you properly scale data to prevent leakage?
scaler.fit(X_train), then transform both: X_train_scaled = scaler.transform(X_train) and X_test_scaled = scaler.transform(X_test). Never fit on combined data.What question should you ask for every feature to detect leakage?
Why does data augmentation potentially cause leakage?
What is TimeSeriesSplit and why use it?
Give the mathematical reason why target leakage breaks ML assumptions :: ML assumes we minimize E[(f(X) - y)²] where X is independent of y. With target leakage, features become X' = g(X, y), so we train on the distribution P(X', y) with dependence, but deploy on P(X, y), creating unbounded generalization error.
What is the 80/20 leakage prevention strategy?
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho beta, data leakage ka core idea ekdum simple hai - ye tab hota hai jab tumhare model ko training ke time aisi information mil jaati hai jo real world mein prediction ke waqt available hi nahi hogi. Socho jaise tumne exam se pehle hi answer key dekh li - obviously tum test mein 99% le aaoge, but jab actual zindagi mein wahi knowledge apply karna hoga tab tum fail ho jaoge. Same cheez model ke saath hoti hai - training aur validation pe deceptively high accuracy dikhti hai, par production mein deploy karte hi wo 99% se 60% pe gir jaati hai. Isliye ye topic itna important hai, kyunki bahut saare beginners yahi galti karte hain aur unhe samajh hi nahi aata ki model achha score kyun de raha hai par kaam kyun nahi kar raha.
Ab intuition thoda deep samjho. Machine learning ka fundamental assumption ye hai ki future bhi past jaisa hi dikhega - matlab training data, test data aur production data ka distribution same hona chahiye. Leakage isi assumption ko todta hai. Iske teen main types hain - target leakage jahan tum aisi features use karte ho jo actual mein target variable se hi derive hui hain (jaise fraud example mein account_balance_after_dispute, jo fraud confirm hone ke baad calculate hoti hai). Yahan causal direction ulta hai - fraud dispute cause karta hai, dispute balance change karta hai, toh us feature ko use karna matlab answer already jaan lena. Doosra hai train-test contamination, jahan test set ki info galti se training mein aa jaati hai. Aur teesra temporal leakage, jahan future ka data past ki predictions mein leak ho jaata hai.
Mathematically dekho toh baat clear ho jaati hai - jab tumhari feature X_j = h(y) + noise ban jaati hai, matlab feature target ka near-perfect encoding hai, toh model easily y ko reverse-engineer kar leta hai aur training error almost zero aa jaata hai. Par production mein wahi feature available nahi hoti ya bina y jaane compute hoti hai, isliye real error bahut zyada ho jaata hai. Yahi gap - training performance aur actual performance ke beech ka fasla - unbounded ho sakta hai. Toh yaad rakhna, hamesha khud se poochho: "Kya ye feature prediction ke exact moment pe genuinely available hogi?" Agar answer no hai, toh wo leakage hai aur usko hatana zaroori hai.