Перейти к основному содержимому

Кодирование категориальных признаков

Разработчику Аналитику

Категориальные столбцы — цвет, размер, тип продукта, город — хранят метки, а не числа. Большинство алгоритмов машинного обучения (линейные модели, SVM, нейросети, градиентный бустинг на «сырых» категориях) ожидают числовой ввод. Задача предобработки — перевести категории в признаки, которые модель может сравнивать и взвешивать.

Ниже — семь распространённых техник. Они дополняют, а не заменяют друг друга: выбор зависит от типа категории (номинальная или порядковая), числа уникальных значений (кардинальности) и требований модели (линейность, деревья, нейросети).

Контекст типов данных в аналитике — в Data Science. Пайплайн предобработки в общей статье — Машинное обучение.


Сводная таблица

ТехникаРезультатКогда уместна
One-hotПо столбцу на каждую категорию (0/1)Номинальные признаки, мало категорий, линейные модели
DummyOne-hot без одного столбцаРегрессия с константой, избежание мультиколлинеарности
EffectDummy, но «базовая» категория = −1То же, что dummy; удобнее в некоторых статистических пакетах
LabelОдно целое на категориюДеревья и бустинг; осторожно с линейными моделями
OrdinalЦелые с сохранением порядкаРазмер, рейтинг, класс обслуживания
CountЧастота категории в обучающей выборкеВысокая кардинальность, эвристика «популярности»
BinaryБиты целочисленного кодаМного категорий, нужно меньше столбцов, чем при one-hot

One-hot encoding

Исходный столбец Color с категориями Green, Red, Black, Orange превращается в четыре бинарных признака. В строке ровно один столбец равен 1, остальные — 0.

ColorGreenRedBlackOrange
Green1000
Red0100
Black0010
Orange0001

Категории не упорядочены — столбцы равноправны. Подходит для логистической регрессии, нейросетей, k-NN. Минус при тысячах уникальных значений (например, user_id) — взрыв размерности матрицы признаков.

В scikit-learn — OneHotEncoder (часто внутри ColumnTransformer, см. пример в статье про ML).


Dummy encoding

Вариант one-hot: один столбец удаляют (часто случайно или по алфавиту — здесь убрали Orange). Строка из одних нулей в оставшихся столбцах означает удалённую категорию.

ColorGreenRedBlack
Green100
Red010
Black001
Orange000

Так убирают линейную зависимость между столбцами (мультиколлинеарность), если в модели уже есть свободный член (intercept). В pandaspd.get_dummies(..., drop_first=True).


Effect encoding

Тот же каркас, что у dummy, но строка «базовой» (удалённой) категории кодируется не нулями, а −1 во всех столбцах.

ColorGreenRedBlack
Green100
Red010
Black001
Orange−1−1−1

Используется в статистике и некоторых R-пакетах (contrasts). Смысл тот же, что у dummy: одна категория — опорная, остальные сравниваются с ней.


Label encoding

Каждой уникальной категории присваивают целое число (обычно 0, 1, 2, … по порядку появления или по алфавиту).

ColorColor_label
Green1
Red2
Black3
Green1

Один столбец вместо нескольких — компактно. Для номинальных признаков числа 1 < 2 < 3 не отражают реальных отношений, но модель может ошибочно трактовать их как порядок. Деревья решений и градиентный бустинг (XGBoost, LightGBM, CatBoost) часто работают с label encoding напрямую; для линейной регрессии и MLP над номинальными полями лучше one-hot.

sklearn.preprocessing.LabelEncoder — для целевой переменной и одномерных столбцов; для таблицы удобнее astype('category').cat.codes в pandas.


Ordinal encoding

Как label encoding, но числа отражают порядок категорий (XS < S < M < L).

SizeSize_ord
XS1
S2
M3
L4

Используют для шкал «мало / средне / много», звёзд рейтинга, классов образования. Порядок меток задаёт человек; кодировщик не угадывает его из данных. OrdinalEncoder в sklearn принимает явный список categories=[['XS','S','M','L']].


Count encoding

Категорию заменяют числом появлений этой категории в обучающей выборке (на тесте — частоты с обучения, иначе утечка).

ColorColor_count
Green2
Red1
Black1
Green2

Простая эвристика для признаков с большим числом уникальных значений (ID магазина, хеш тега). Риск — редкие категории получают 1, частые — большие числа; связь с целевой переменной слабая. Близкий и более сильный приём — target encoding (среднее целевой по категории); его нужно считать только на train и с регуляризацией, чтобы избежать переобучения.


Binary encoding

Сначала категории нумеруют (0, 1, 2, …), затем целое записывают в двоичном виде и каждый бит выносят в отдельный столбец.

ColorКодColor_0Color_1
Green000
Red101
Black210
Green000

Для (k) категорий нужно примерно (\lceil \log_2 k \rceil) столбцов вместо (k) при one-hot — экономия памяти при высокой кардинальности. Минус — произвольный порядок меток влияет на биты; для номинальных признаков это менее интерпретируемо, чем one-hot.


Как выбрать метод

Утечка данных

Count encoding, target encoding и любые статистики по категориям считают только на обучающей выборке, затем применяют к validation и test. Иначе информация о целевой переменной «просачивается» в признаки и метрики завышаются.

Практика в sklearn

Объединяйте числовые и категориальные преобразования в ColumnTransformer + Pipeline, чтобы на inference применялась та же схема кодирования, что и при fit. Неизвестные категории на проде — параметр handle_unknown='ignore' у OneHotEncoder.


Пример — несколько кодировщиков

import pandas as pd
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder, LabelEncoder

df = pd.DataFrame({
"color": ["Green", "Red", "Black", "Green"],
"size": ["XS", "S", "L", "M"],
})

# One-hot (dummy — drop_first=True)
color_ohe = pd.get_dummies(df["color"], prefix="color")
# drop_first=True даёт dummy encoding

# Ordinal — порядок задаём явно
size_ord = OrdinalEncoder(categories=[["XS", "S", "M", "L"]])
df["size_ord"] = size_ord.fit_transform(df[["size"]])

# Label — одна колонка целых
le = LabelEncoder()
df["color_label"] = le.fit_transform(df["color"])

# Count — только по train; здесь иллюстрация на всём df
counts = df["color"].value_counts()
df["color_count"] = df["color"].map(counts)

Для production-пайплайна предпочтительнее зафиксировать ColumnTransformer в конвейере из статьи про ML, а не вызывать get_dummies отдельно на каждом датасете.


Связанные материалы


См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").