Back to Technical Blog
Machine Learning 9 min read

Preventing Data Leakage in Machine Learning

Practical strategies for detecting and avoiding target leakage and client-level feature overlap in large-scale datasets, drawing from real-world ML experience on 78.8M search performance records.

Data Leakage Cross Validation Random Forest

Introduction & Technical Context

Data leakage is one of the most common yet deceptive pitfalls in real-world machine learning. While working on the FlyRank search-performance prediction system—analyzing over 78.8 million daily search-performance records—preventing temporal and client-level target leakage was crucial for building a trustworthy ranking and prediction pipeline.

1. Understanding Sources of Data Leakage in Search Analytics

Data leakage occurs when information from outside the training dataset (or future temporal window) unintentionally influences model training. In large search analytics pipelines, leakage typically manifests when rows are split randomly across train/test when multiple rows belong to the same client domain, allowing the model to memorize client-specific baselines rather than learning generalizable signals.

2. Client-Grouped & Time-Based Cross-Validation

To prevent client overlap, I implemented client-grouped cross-validation (GroupKFold / custom client splits), ensuring all daily records for a specific client domain were restricted exclusively to either the training fold or the validation fold.

Client-Grouped Cross-Validation to prevent target leakagepython
from sklearn.model_selection import GroupKFold
import numpy as np

# Prevent client domain overlap between train and validation splits
gkf = GroupKFold(n_splits=5)

for fold, (train_idx, val_idx) in enumerate(gkf.split(X, y, groups=client_ids)):
    X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
    y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
    
    # Fit preprocessing pipeline ONLY on X_train to avoid data leakage
    pipeline.fit(X_train, y_train)
    score = pipeline.score(X_val, y_val)
    print(f"Fold {fold} Validation Score: {score:.4f}")

3. Evaluating Tree Ensembles & Benchmark Results

Comparing baseline Logistic Regression against Random Forest, XGBoost, LightGBM, and CatBoost revealed that models evaluated under random splits showed artificially inflated metrics. Once evaluated under strict client-grouped validation, Random Forest achieved an ROC-AUC of 0.814, demonstrating realistic generalization to completely unseen client domains.

Key Engineering Takeaways

  • Never use standard random train/test splits on grouped or domain-structured datasets.
  • Fit all preprocessing, scaling, and aggregation steps strictly on training folds to prevent feature leakage.
  • A realistic validation setup is more important than chasing ungrounded 0.99 AUC scores on leaked data.