Splitting Data Without Cheating
Building leak-free data splits that accurately reflect real-world model deployment conditions.
Splitting Strategy Matrix
DATA SPLITTING MATRIX
┌──────────────────────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┐
│ 1. RANDOM SPLIT (K-Fold) │ 2. STRATIFIED K-FOLD │ 3. GROUP K-FOLD │ 4. TEMPORAL TIME-SPLIT │
├──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┤
│ Standard i.i.d. data │ Imbalanced classes │ Grouped observations │ Time-series, events, │
│ (Tabular, independent) │ (Fraud 1%, Rare disease) │ (Patient ID, User ID) │ user activity logs │
└──────────────────────────┴──────────────────────────┴──────────────────────────┴──────────────────────────┘
Three Data Leakage Traps to Avoid
Trap 1: Group Leakage (Patient / User Leakage)
Multiple records belong to the same entity (e.g. 5 audio clips from User 102).
- Wrong: Random Split. User 102 appears in both Train and Test sets.
- Right:
GroupKFold(groups=user_id). All records for User 102 stay strictly in 1 fold!
Trap 2: Temporal Leakage (Look-Ahead Bias)
Data has a time component (e.g. financial transactions, user clicks).
- Wrong: Shuffling data randomly. Future transactions leak into past training rows.
- Right: Cutoff Time Split (Train: Jan-Jun, Val: Jul, Test: Aug) or
TimeSeriesSplit.
Trap 3: Global Preprocessing Leakage
Computing scaling parameters or imputer statistics globally:
# WRONG: Leaks test set mean & std into training!
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_all) # BAD!
X_train, X_test = train_test_split(X_scaled)
# RIGHT: Fit strictly on train fold
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # GOOD!
Say this out loud
"Splitting strategy depends on data structure: we use Stratified K-Fold for imbalanced targets, GroupKFold for grouped entities (patient/user IDs), and TimeSeriesSplit for temporal data. The golden rule of machine learning is to fit all transformers, imputers, and scalers strictly on the training set fold, then transform validation and test sets without re-fitting."
Follow-ups to expect
- What is nested cross-validation? Used for unbiased model evaluation when hyperparameter tuning: an outer loop evaluates model generalization performance, while an inner loop tunes hyperparameters, preventing hyperparameter overfitting to the validation set.
- How do you choose the split ratio (e.g. 80/10/10 vs 98/1/1)? For small datasets ($N < 10,000$), 80/10/10 or 5-fold CV is standard. For massive datasets ($N > 10,000,000$), 98/1/1 is preferred because 1% of 10M provides 100,000 samples—more than enough for precise validation evaluation.
Check yourself
Why must medical AI models use GroupKFold splitting on `patient_id` rather than standard random K-Fold splitting?