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

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

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

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

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

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


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

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


Отбор признаков

Перед кодированием имеет смысл удалить столбцы, которые не помогают цели. Лишние признаки увеличивают размерность, время обучения и риск переобучения; слабо коррелирующие с y могут добавлять шум.

Пример из практики: в датасете об endangered languages столбец "название на испанском" дублирует информацию и не предсказывает исчезновение языка — его убирают до обучения. В проекте Melbourne из выборки убирают адрес, координаты и дату продажи, оставляя пригород и площадь.

Отбор — отдельный большой раздел (filter/wrapper/embedded); на старте достаточно domain-знаний и df.drop(columns=...).


Биннинг

Биннинг (дискретизация) — превращение непрерывного числа в интервалы (корзины). Возраст 34 → "30–40"; доход → "низкий / средний / высокий".

Зачем:

  • линейным моделям проще аппроксимировать нелинейную зависимость;
  • устойчивость к выбросам (экстремальный доход попадает в верхнюю корзину);
  • интерпретация для бизнеса.

import pandas as pd

df = pd.DataFrame({"age": [22, 34, 41, 55, 19]})
df["age_bin"] = pd.cut(df["age"], bins=[0, 25, 40, 60, 100], labels=False)
# затем age_bin кодируют ordinal или one-hot

Границы bins задают вручную или через qcut (квантили). На train подбирают пороги, на test применяют те же — иначе утечка. В sklearn — KBinsDiscretizer.


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

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

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

Практика в sklearn

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


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

Код ITЗагрузка примера кода…

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


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