Ответ
Я использовал комбинацию критериев, чтобы остановить отбор признаков до переобучения. Вот мои практические правила:
Основные критерии остановки:
-
Отсутствие значимого улучшения на валидации. Это главный критерий. Я останавливаюсь, когда добавление/удаление очередного признака не даёт прироста целевой метрики (например,
AUC-ROCилиF1-score) на отдельном валидационном наборе больше, чем на заданный порог (например,threshold = 0.001).# Упрощённая логика внутри цикла отбора current_score = evaluate_model(X_train[:, selected], y_train, X_val[:, selected], y_val) if len(history_scores) > 1: improvement = current_score - max(history_scores) if improvement < IMPROVEMENT_THRESHOLD: print(f"Остановка. Улучшение {improvement:.4f} < порога {IMPROVEMENT_THRESHOLD}") break history_scores.append(current_score) -
Минимизация информационного критерия (AIC/BIC). Для линейных моделей я часто останавливался, когда значение AIC переставало уменьшаться. Это автоматически балансирует качество и сложность модели.
-
Контроль переобучения через кросс-валидацию. Я запускал
StratifiedKFoldна каждом шаге. Если средняя метрика на валидационных фолдах начинала снижаться, а на тренировочных — расти, это явный сигнал к остановке. -
Статистическая значимость (p-value). При использовании
statsmodelsдля линейной/логистической регрессии я добавлял только признаки сp-value < 0.05и удалял те, у которыхp-valueстановился выше0.1.
Практический совет: Я никогда не полагался на один критерий. Например, в задаче предсказания оттока я сочетал контроль AUC на валидации с мониторингом AIC. Как только оба критерия переставали улучшаться два шага подряд — процесс останавливался.
Ответ 18+ 🔞
Блин, слушай, вот эта тема с отбором признаков — это вообще отдельная песня, ёпта. Я там столько раз наступал на грабли, что уже, блядь, лысину на лбу отбил. Но в итоге выработал себе чёткие правила, чтобы не переобучаться, как последний идиот.
На чём я обычно тормозу:
-
Когда на валидации нихуя не улучшается. Это святое, блядь. Если после очередного круга добавления или удаления какой-нибудь фичи метрика на отложенной выборке (ну, там
AUC-ROC) подпрыгивает меньше, чем на какую-то заранее выбранную погрешность (скажем, на 0.001), то всё — стоп машина. Зачем дальше-то мучать данные?# Примерно так это внутри выглядит current_score = evaluate_model(X_train[:, selected], y_train, X_val[:, selected], y_val) if len(history_scores) > 1: improvement = current_score - max(history_scores) if improvement < IMPROVEMENT_THRESHOLD: print(f"Всё, приехали. Прирост {improvement:.4f} — это даже не чих, а так, пшик.") break history_scores.append(current_score) -
Информационные критерии (AIC/BIC). Для всяких линейных моделей — просто красота. Как только этот самый AIC перестаёт падать и начинает ёрзать на месте, я понимаю — дальше только усложнять модель без толку. Баланс между качеством и сложностью, ёбать копать!
-
Кросс-валидация, чтобы не бздеть. Запускаю на каждом шаге
StratifiedKFold. И если вижу, что на тренировочных фолдах метрика лезет вверх, а на валидационных — уже ползёт вниз, это прям красная лампочка: «Чувак, ты уже переобучаешься, остановись, ебушки-воробушки!». -
Статистическая значимость, мать её. Когда через
statsmodelsработаю, то добавляю только те признаки, у которыхp-valueменьше 0.05. А если у уже сидящего в модели признакаp-valueвдруг вылез за 0.1 — вышвыриваю его без сожаления. Мертвый груз, хуй с горы.
Главный лайфхак, ёпта: Никогда не доверяй одному критерию. Один может соврать. Я, например, в одной задаче по оттоку клиентов одновременно следил и за AUC на валидации, и за AIC. И если оба этих упрямых осла два шага подряд упирались и не хотели улучшаться — всё, я сдавался. Процесс завершён, модель готова, можно идти пить чай.