MiddleДебаггингЧастоЕщё не отвечали
Скейлер, импутер и отбор признаков обучены до деления — что именно утекает и как это чинить?
Метрика кросс-валидации этого классификатора сильно выше метрики на отложенных данных.
Ограничения:
X— широкая таблица с пропусками;y— бинарная цель.- Саму модель и число частей менять нельзя.
- Исправить нужно только то, как обучаются шаги препроцессинга.
X = StandardScaler().fit_transform(X)
X = SimpleImputer(strategy="mean").fit_transform(X)
X = SelectKBest(f_classif, k=20).fit_transform(X, y)
scores = cross_val_score(model, X, y, cv=5)
Опишите, что утекает на каждом шаге, и перепишите код так, чтобы ничего не обучалось вне обучающей части.
Обучение их на всей таблице заносит отложенные строки в статистики обучения: скейлер несёт средние и дисперсии отложенных строк, импутер заполняет из них, а отбор читает отложенные метки — худшая утечка. Pipeline переобучает каждый шаг на обучающей части.
- ✗Считать преобразования без учителя безопасными, раз они не читают цель
- ✗Масштабировать всё заранее ради удобства и делить массив уже после
- ✗Отбирать признаки на всей таблице и потом кросс-валидировать выживших
- →Почему target encoding требует внутреннего деления даже внутри корректного pipeline?
- →Как применить ту же дисциплину к шагу ресемплинга, например
SMOTE?
Утекает каждый шаг, и по-разному.
StandardScalerна всей таблице считает среднее и дисперсию по отложенным строкам тоже — обучающая часть узнаёт масштаб данных, которых ещё не должна видеть.SimpleImputerзаполняет пропуски средним по всей таблице, то есть значением, вычисленным в том числе по отложенным строкам.SelectKBest— худший случай: он читаетyпо всем строкам, поэтому выбранные 20 признаков уже подогнаны под отложенные метки. Метрика после такого отбора завышена сильнее всего.
Решение — собрать шаги в Pipeline и передать его кросс-валидатору. Тогда fit каждого шага вызывается только на обучающей части, а на отложенной — лишь transform.
pipe = Pipeline([
("impute", SimpleImputer(strategy="mean")),
("scale", StandardScaler()),
("select", SelectKBest(f_classif, k=20)),
("model", model),
])
scores = cross_val_score(pipe, X, y, cv=5)
Импутацию ставят до масштабирования, иначе среднее считается по таблице с пропусками.