Target Encoding: кодирование категориальных признаков без утечки данных

Target Encoding: кодирование категориальных признаков без утечки данных

У вас столбец «город» с 800 уникальными значениями. One-hot encoding превратит его в 800 бинарных столбцов, создав разреженную матрицу и модель, которая переобучится уже на третьей эпохе. Label encoding присвоит значениям числа от 0 до 799, но модель может ошибочно интерпретировать это как порядок: будто Москва (0) «меньше» Владивостока (799). Frequency encoding укажет на частоту, но проигнорирует целевую переменную — например, Москва и Петербург могут быть частыми, но сильно отличаться по конверсии.

Что такое target encoding

Target encoding — это способ кодирования категориальных признаков, при котором каждое значение заменяется агрегированной статистикой целевой переменной по этой категории. Для регрессии — средним значением, для классификации — долей положительного класса. Например, город «Москва» с конверсией 12% становится числом 0.12, а «Тюмень» с конверсией 8% — 0.08.

Идея проста, но таит опасность: если посчитать среднее по всей обучающей выборке и использовать его в тех же данных, возникнет утечка целевой переменной (target leakage). Модель будет переобучаться, показывая завышенные метрики на трейне и проваливаясь на новых данных.

Как работает: базовая формула

Для каждого значения категории c вычисляется сглаженное среднее:

где count(c) — количество наблюдений категории, mean_target(c) — среднее значение целевой переменной в категории, global_mean — общее среднее по выборке, m — параметр сглаживания (smoothing).

Сглаживание предотвращает переуверенность в редких категориях. Например, если категория встретилась один раз с target=1, без сглаживания её код будет 1.0 — что нереалистично. Сглаживание «подтягивает» такие значения к global_mean.

При m=0 сглаживания нет. При m=100 категории с менее чем 100 наблюдениями будут близки к глобальному среднему. Типичные значения m — от 10 до 300, подбираются на валидации.

Проблема: target leakage

Главная ошибка — использовать статистику по всей обучающей выборке для кодирования той же выборки. Каждая строка участвует в расчёте своего признака, и модель фактически подглядывает ответ.

Особенно критично для редких категорий. Например, город с тремя наблюдениями и target=1 везде получит код 1.0. Модель запомнит эти строки, вместо обобщения.

Решение 1: Leave-One-Out (LOO)

Для каждой строки i среднее считается по всем строкам категории, кроме самой строки i. Это снижает утечку, но не устраняет её полностью — оставшиеся N-1 строк всё ещё коррелируют с целевой переменной.

Решение 2: K-Fold Target Encoding (рекомендуется)

Обучающая выборка делится на K фолдов. Для строк фолда k encoding вычисляется только по другим фолдам — без участия строк из k. При K=5 утечка практически отсутствует.

Для тестовой выборки encoding рассчитывается по всей обучающей — это допустимо, так как тест не участвует в обучении.

Готовые реализации

В библиотеке category_encoders (совместимой с sklearn) можно использовать TargetEncoder с кросс-валидацией. При использовании cross_val_score и пайплайнов encoder обучается только на train-фолде — это безопасно.

Но если вручную вызвать encoder.fit_transform(X_train, y_train), возникнет утечка, так как статистики считаются по всему X_train.

Когда target encoding лучше альтернатив

  • Высокая кардинальность. IP-адреса, почтовые индексы, ID товаров, user agents — тысячи или десятки тысяч уникальных значений. One-hot encoding создаст слишком много столбцов, label encoding не передаст смысла. Target encoding сжимает всё в один информативный числовой признак.
  • Древесные модели. XGBoost, LightGBM, CatBoost хорошо работают с target encoding, так как строят сплиты по порогам. Например: «если encoding города > 0.15, идём влево» — то есть «если конверсия выше 15%».

CatBoost реализует target encoding автоматически (ordered target statistics) с защитой от утечки. Если вы используете CatBoost, отдельное кодирование не нужно — просто передайте категориальные признаки через параметр cat_features.

  • Линейные модели. Target encoding здесь тоже применим, но эффект слабее — линейные модели могут извлечь столько же информации из one-hot при достаточном объёме данных. Основное преимущество — снижение размерности при высокой кардинальности.

Когда target encoding не нужен

  1. Низкая кардинальность (менее 10–15 значений). Для признаков вроде пола, дня недели или типа устройства лучше использовать one-hot — он не создаёт риска утечки и не усложняет модель.
  2. Мало данных. Если в категории всего 5 наблюдений, среднее — это шум. Сглаживание поможет, но лучше сгруппировать редкие значения в «другое» и применить one-hot.
  3. Целевая переменная — непрерывная с высокой дисперсией. Среднее будет зашумлённым. Рассмотрите медиану или quantile encoding.

Что ещё можно кодировать кроме среднего

Target encoding не ограничивается средним. Можно использовать и другие агрегаты:

std — показывает стабильность целевой переменной в категории. Например, город с mean=0.1 и std=0.02 — стабильно низкая конверсия; с std=0.15 — нестабильный, среднее не показательно.

count — частота категории. Сам по себе может быть полезным признаком: популярные и редкие города могут вести себя по-разному.

Для каждого агрегата применяйте тот же K-Fold подход, чтобы избежать утечки. Но помните: чем больше признаков на основе целевой переменной, тем выше риск переобучения — даже при правильной валидации.

  • Считайте encoding с помощью K-Fold на трейне (K=5 или K=10). Никогда не используйте fit_transform на всей обучающей выборке.
  • Для теста и прода — применяйте encoding на основе статистик по всему трейну. Сохраняйте маппинг (словарь «категория → значение») как артефакт модели.
  • Новые категории (не встречавшиеся в трейне) заменяйте на global_mean, а не на 0 или NaN.
  • Подбирайте параметр m (smoothing) на валидации. Обычно — от 10 до 100 для средних датасетов, от 100 до 500 для больших.
  • Мониторьте drift. Если распределение категорий на проде сместилось (например, появился новый город с 30% трафика), encoding устаревает. Периодическое переобучение — важная практика.
Читать оригинал