One-Hot Encoding простыми словами
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Зачем это знать
ML-модели работают с числами, не с категориями. Если у вас колонка city с значениями ['Moscow', 'SPb', 'Kazan'], модель не поймёт их напрямую. Нужно закодировать в числа. Способов кодирования — несколько, и от выбора зависит performance модели.
One-hot encoding — самый распространённый способ. На собеседовании DS/ML вас обязательно спросят: «как закодируете категориальную переменную», «что такое one-hot», «когда использовать target encoding». Без этих знаний — середняк уровень.
В статье — полное понимание:
- Что такое one-hot на примере
- Плюсы и минусы
- Альтернативы: label encoding, target encoding, binary encoding
- Когда какое применять
- Practical в 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).
Зачем: избежать multicollinearity в линейных моделях. Для tree-based моделей (Random Forest, XGBoost) не обязательно.
Когда one-hot работает хорошо
- Небольшое количество категорий (2-20)
- Категории без порядка (номинальные)
- Модель линейная или tree-based
Когда one-hot работает плохо
- Много уникальных значений (сотни городов)
- Большие dataset (размер взрывается)
- Redundant для tree-based (можно label encoding)
Альтернативы
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? Для linear моделей плохо.
Для tree-based — ок, модель игнорирует порядок.
2. Target Encoding
Заменяет категорию на среднее значение target по этой категории:
Moscow → 0.15 (avg conversion)
SPb → 0.12
Kazan → 0.08# manual
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
Заменяет на frequency появления:
Moscow (1000 раз) → 1000 / 10000 = 0.1
SPb (500) → 0.05Когда какое использовать
| Cardinality | Model | Выбор |
|---|---|---|
| Low (2-10) | любая | One-Hot |
| Medium (10-50) | tree-based | Label или One-Hot |
| Medium | linear | One-Hot |
| High (50+) | любая | Target / Frequency |
| Very high (1000+) | любая | Embeddings (deep learning) |
Handling unseen categories
Проблема: в 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 колонок. Memory explosion.
2. Не сохранить encoder
Обучили encoder на train, забыли save. В prod новая инструкция не закодируется.
3. Label encoding для linear
Модель решит, что Moscow < SPb < Kazan. Лучше one-hot.
4. Target encoding без CV
Target leakage: среднее target включает саму строку. Нужен specific leave-one-out подход.
Связанные темы
FAQ
Sparse matrix?
Для big data — да, memory-efficient. В sklearn sparse_output=True.
Drop first обязательно?
Для linear — рекомендуется. Tree-based — по желанию.
Категория встречается 2 раза — удалять?
Обычно удаляют или заменяют на «Other», если cardinality большая.
Какой pipeline в sklearn?
ColumnTransformer для разных типов колонок + OneHotEncoder.
Тренируйте ML — откройте тренажёр с 1500+ вопросами для собесов.