Собесов

Сценарий ML: leakage в train/val/test split

ML / Data ScienceOverfitting и регуляризацияСложнаяSenior

Условие

ROC AUC на val 0.92, на production 0.71. Перечислите типичные источники leakage в split и как их избежать.

Решение

Подход

Leakage = информация из test/future попала в train. Источники:

  1. Random split при temporal-зависимости: train содержит будущие точки, test — прошлые. Корректно: time-based split.
  2. Random split при group-зависимости: один user/object в train и test → memorization. Решение: GroupKFold по user.
  3. Target encoding до split: средние target по категории посчитаны на всех данных, включая val.
  4. Scaling / imputation до split: mean/std из всех данных.
  5. Feature selection до CV: фичи выбраны по корреляции с y на всём dataset.
  6. Hyperparameter tuning на test: tuning peeks test → biased estimate.
  7. 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

Подводные камни

  1. Самая частая: применили StandardScaler до train/test split. На больших dataset разница маленькая, но на 1000 строках уязвима.
  2. KFold при наличии user-кластеров: один user в train + test → AUC завышен на 5-15%.
  3. Time series: random KFold катастрофически переоценивает качество. TimeSeriesSplit с expanding window.
  4. Hyperparameter tuning на test: лучшая модель «переобучилась» под тестовый split. Нужен nested CV или train/val/test 3-way.
  5. «Дата создания» как фича — может быть прокси для будущих событий (создан после момента 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.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти