One-Hot Encoding простыми словами

Проверь себя · 1/3разбор после ответа
Вы хотите заменить NULL в столбце источника перехода на значение 'direct'. Какой вариант записан корректно и эквивалентен по смыслу?

Зачем это знать

ML-модели работают с числами, а не с категориями. Если у вас колонка city со значениями ['Moscow', 'SPb', 'Kazan'], модель не поймёт их напрямую. Нужно закодировать в числа. Способов кодирования несколько, и от выбора зависит качество модели.

One-hot encoding — самый распространённый способ. На собеседовании DS/ML обязательно спросят: «как закодируете категориальную переменную», «что такое one-hot», «когда использовать target encoding». Без этих знаний — уровень ниже middle.

В статье — полное понимание:

  • Что такое one-hot на примере.
  • Плюсы и минусы.
  • Альтернативы: label encoding, target encoding, binary encoding.
  • Когда какое применять.
  • Практика в pandas и sklearn.

Короткое объяснение

One-hot превращает категориальную переменную в набор бинарных (0/1) колонок — по одной на каждое уникальное значение.

Пример

city
----
Moscow
SPb
Moscow
Kazan

После one-hot:

city_Moscow  city_SPb  city_Kazan
     1          0          0
     0          1          0
     1          0          0
     0          0          1

Каждое значение → отдельная колонка, в ней 1 если match.

В pandas

df_encoded = pd.get_dummies(df, columns=['city'])

Или через sklearn:

from sklearn.preprocessing import OneHotEncoder

encoder = OneHotEncoder(sparse_output=False)
encoded = encoder.fit_transform(df[['city']])

drop_first

pd.get_dummies(df, columns=['city'], drop_first=True)

Удаляет первую колонку (Moscow). Она и так выводится из остальных (если все 0 → Moscow).

Зачем: избежать мультиколлинеарности в линейных моделях. Для tree-based моделей (Random Forest, XGBoost) не обязательно.

Когда one-hot работает хорошо

  • Небольшое количество категорий (2–20).
  • Категории без порядка (номинальные).
  • Модель линейная или tree-based.

Когда one-hot работает плохо

  • Много уникальных значений (сотни городов).
  • Большие датасеты (размер матрицы взрывается).
  • Избыточно для tree-based (можно обойтись label encoding).
Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Альтернативы

1. Label Encoding

Просто целые числа: Moscow=0, SPb=1, Kazan=2.

from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
df['city_encoded'] = encoder.fit_transform(df['city'])

Плюсы: одна колонка, компактно. Минусы: вводит ложный порядок. Moscow < SPb < Kazan? Для линейных моделей плохо.

Для tree-based — ок, модель игнорирует порядок.

2. Target Encoding

Заменяет категорию на среднее значение target по этой категории:

Moscow → 0.15 (средняя конверсия)
SPb →    0.12
Kazan →  0.08
# вручную
city_target = df.groupby('city')['target'].mean()
df['city_encoded'] = df['city'].map(city_target)

Плюсы: работает для high cardinality (много уникальных значений). Минусы: риск data leakage, нужна регуляризация.

3. Binary Encoding

Представляет числа в двоичном виде.

100 уникальных значений → label encoding даёт 100 чисел → 7 бит в двоичном представлении → 7 колонок.

Меньше, чем one-hot, при high cardinality.

4. Frequency Encoding

Заменяет категорию на её частоту в данных:

Moscow (1000 раз) → 1000 / 10000 = 0.1
SPb (500) → 0.05

Когда какое использовать

Cardinality Модель Выбор
Low (2–10) любая One-Hot
Medium (10–50) tree-based Label или One-Hot
Medium линейная One-Hot
High (50+) любая Target / Frequency
Very high (1000+) любая Embeddings (deep learning)

Новые категории в test

Проблема: в train есть 'Moscow', в test появится 'Новгород', которого в train не было.

encoder = OneHotEncoder(handle_unknown='ignore')

Или заменить редкие на 'Other' до кодирования.

На собесе

«Что такое one-hot encoding?» Каждое значение категории превращается в отдельную бинарную колонку.

«Когда label encoding?» Tree-based модели с категориями без естественного порядка.

«Минусы target encoding?» Data leakage, если не разделить правильно train и test.

«Категория из 1000 городов — как?» Target или frequency encoding вместо one-hot.

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

1. One-hot на high cardinality

10 000 категорий → 10 000 колонок. Разрыв памяти.

2. Не сохранить encoder

Обучили encoder на train, забыли сохранить. В проде новое значение не закодируется тем же способом.

3. Label encoding для линейных моделей

Модель решит, что Moscow < SPb < Kazan. Лучше one-hot.

4. Target encoding без CV

Утечка таргета: среднее включает саму строку. Нужен leave-one-out или обучение encoder только на train-фолде.

Связанные темы

FAQ

Sparse matrix?

Для big data — да, memory-efficient. В sklearn sparse_output=True.

Drop first обязательно?

Для linear — рекомендуется. Tree-based — по желанию.

Категория встречается 2 раза — удалять?

Обычно удаляют или заменяют на «Other», если cardinality большая.

Какой pipeline в sklearn?

ColumnTransformer для разных типов колонок + OneHotEncoder.