← Назад к списку
ТехническаяData Science и MLMiddle

Какие способы кодирования категориальных признаков вы знаете и как выбрать подходящий?

Короткий ответ

  • One-hot: просто и честно, но раздувает размерность
  • Label/ordinal encoding — только для порядковых категорий
  • Target encoding мощен, но опасен утечкой
  • Частотное кодирование — счётчики встречаемости категории
  • Высококардинальные признаки: хэширование или эмбеддинги
  • CatBoost кодирует категории сам, упорядоченно
  • Новые категории в проде нужно обрабатывать явно

Выбор кодирования зависит от кардинальности, типа модели и риска утечки: one-hot для малых словарей, target encoding с регуляризацией или встроенные механизмы бустингов для больших.

Как сказать вслух

пример ответа

Для небольшого числа категорий я обычно беру one-hot — он честный и понятный. Порядковое кодирование использую только там, где у категорий есть естественный порядок. Для признаков с тысячами значений хорошо работает target encoding — заменяем категорию средним таргетом, но его обязательно считать аккуратно, на кросс-валидации, иначе утечём. А если работаю с CatBoost, часто отдаю категории ему как есть.

Подробный ответ

Основной ответ

Основные приёмы: one-hot encoding — бинарный столбец на категорию, хорош для линейных моделей и малой кардинальности, но взрывает размерность; ordinal/label encoding — подходит только для упорядоченных категорий (размер, грейд), иначе навязывает модели ложный порядок (хотя деревья к этому терпимее); frequency encoding — замена категории её частотой; target encoding — замена средним значением таргета по категории, мощен для высокой кардинальности, но требует защиты от утечки: сглаживание к глобальному среднему и вычисление по out-of-fold схеме. Для очень больших словарей — feature hashing или обучаемые эмбеддинги в нейросетях. CatBoost применяет ordered target statistics из коробки. Отдельно продумывают обработку редких и новых категорий: группа «other» и дефолтное значение в проде.

Ключевые моменты

  • Модель диктует выбор. Линейным моделям нужен one-hot, деревья переваривают ordinal, бустинги умеют свои счётчики.
  • Target encoding без утечки. Считать только по train-части фолда, сглаживать по размеру категории; наивная версия по всей выборке — классическая утечка.
  • Высокая кардинальность. Тысячи значений: target/frequency encoding, хэширование или эмбеддинги вместо one-hot.
  • Прод-устойчивость. Новые и редкие категории должны иметь явный fallback, иначе пайплайн упадёт или выдаст мусор.

Практический контекст

Практический вопрос: интервьюер проверяет не словарь терминов, а понимание последствий — что будет с one-hot на признаке «город» с десятью тысячами значений, как не утечь с target encoding. Это ежедневная рутина табличного ML; грамотная обработка категорий часто даёт больше прироста качества, чем смена модели. Хорошо прозвучит опыт сравнения кодировок на конкретной задаче.

Пример кода

import pandas as pd
from sklearn.model_selection import KFold

# Target encoding без утечки: out-of-fold среднее со сглаживанием
def target_encode(df, col, target, n_splits=5, alpha=10):
    global_mean = df[target].mean()
    encoded = pd.Series(index=df.index, dtype=float)
    for tr_idx, val_idx in KFold(n_splits, shuffle=True, random_state=42).split(df):
        tr = df.iloc[tr_idx]
        stats = tr.groupby(col)[target].agg(["mean", "count"])
        smooth = (stats["mean"] * stats["count"] + global_mean * alpha) / (
            stats["count"] + alpha
        )
        encoded.iloc[val_idx] = df.iloc[val_idx][col].map(smooth).fillna(global_mean)
    return encoded

df["city_te"] = target_encode(df, "city", "churn")

Частые ошибки

  • Применяют label encoding к неупорядоченным категориям для линейной модели
  • Считают target encoding по всей выборке и получают утечку
  • Забывают про обработку новых категорий, появляющихся после обучения

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru