Условие
ROC AUC на val 0.92, на production 0.71. Перечислите типичные источники leakage в split и как их избежать.
Решение
Подход
Leakage = информация из test/future попала в train. Источники:
- Random split при temporal-зависимости: train содержит будущие точки, test — прошлые. Корректно: time-based split.
- Random split при group-зависимости: один user/object в train и test → memorization. Решение: GroupKFold по user.
- Target encoding до split: средние target по категории посчитаны на всех данных, включая val.
- Scaling / imputation до split: mean/std из всех данных.
- Feature selection до CV: фичи выбраны по корреляции с y на всём dataset.
- Hyperparameter tuning на test: tuning peeks test → biased estimate.
- Future-knowledge features: фича доступна только после события (e.g.
total_ordersвключая будущие).
Реализация: правильный pipeline
from sklearn.model_selection import GroupKFold, TimeSeriesSplit
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
# 1. Scaling внутри pipeline — fit_transform на train fold
pipe = Pipeline([
('scaler', StandardScaler()),
('clf', LogisticRegression())
])
# 2. GroupKFold по user_id
gkf = GroupKFold(n_splits=5)
for tr, te in gkf.split(X, y, groups=user_ids):
pipe.fit(X[tr], y[tr])
score = pipe.score(X[te], y[te])
# 3. Time series split
tscv = TimeSeriesSplit(n_splits=5, test_size=10000)
for tr, te in tscv.split(X_sorted_by_time):
...Target encoding с защитой от leakage
def target_encode_cv(X, y, cat_col, n_splits=5):
"""Out-of-fold target encoding."""
enc = np.zeros(len(X))
kf = KFold(n_splits)
for tr, te in kf.split(X):
means = X.iloc[tr].groupby(cat_col)[y.iloc[tr].name].mean()
enc[te] = X.iloc[te][cat_col].map(means).fillna(y.iloc[tr].mean())
return encПодводные камни
- Самая частая: применили StandardScaler до train/test split. На больших dataset разница маленькая, но на 1000 строках уязвима.
- KFold при наличии user-кластеров: один user в train + test → AUC завышен на 5-15%.
- Time series: random KFold катастрофически переоценивает качество. TimeSeriesSplit с expanding window.
- Hyperparameter tuning на test: лучшая модель «переобучилась» под тестовый split. Нужен nested CV или train/val/test 3-way.
- «Дата создания» как фича — может быть прокси для будущих событий (создан после момента prediction).
Эталонный ответ
Leakage = информация из test/future в train. Источники: random split при time/group зависимости, target encoding/scaling/feature selection до split, tuning на test, future-knowledge features. Решения: GroupKFold/TimeSeriesSplit, pipeline с fit_transform внутри fold, out-of-fold target encoding, nested CV.