Привет! Ты уже знаешь, что модели машинного обучения работают только с числами. Но в реальных данных часто встречаются текстовые категории: «красный», «синий», «зелёный» или «клиент ушёл» / «клиент остался». Как быть?
В этой статье мы разберём:
- Что такое категориальные данные
LabelEncoder— кодирование меток в числаOneHotEncoder— создание бинарных столбцов- Когда и как использовать каждый метод
- Как избежать распространённых ошибок
- Что нужно знать перед началом
- Основная часть
- Что такое категориальные данные?
- LabelEncoder — простое кодирование в числа
- Где использовать LabelEncoder
- Для целевой переменной (y)
- Для порядковых признаков
- OneHotEncoder — бинарное кодирование
- Сравнение OneHotEncoder и LabelEncoder
- Полный пример: подготовка данных для модели
- Когда использовать альтернативы
- Проблема высокой размерности
- Для деревьев решений
- Задачи для закрепления
- Нюансы и подводные камни
- Unseen categories в тестовых данных
- Дамми-ловушка (Dummy Trap)
- LabelEncoder для нескольких колонок
- Частые ошибки и как их избежать
- Ошибка 1: LabelEncoder для номинальных признаков
- Ошибка 2: OneHotEncoder для целевой переменной
- Ошибка 3: Не разделил данные перед кодированием
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный scikit-learn (
pip install scikit-learn) - Базовое понимание машинного обучения
- Знание, что такое признаки (X) и целевая переменная (y)
Совет: Кодирование категорий — обязательный этап предобработки данных. Без него модели не смогут работать с текстовыми данными!
Основная часть
Что такое категориальные данные?
Категориальные данные — это данные, которые принимают ограниченное количество значений (категорий). Они бывают двух типов:
| Тип | Описание | Пример |
|---|---|---|
| Номинальные | Нет порядка между значениями | Цвет: «красный», «синий», «зелёный» |
| Порядковые | Есть логический порядок | Размер: «S», «M», «L», «XL» |
Совет: Различие важно — для номинальных данных нужен
OneHotEncoder, для порядковых можно использоватьLabelEncoder.
LabelEncoder — простое кодирование в числа
LabelEncoder заменяет каждую категорию на целое число (от 0 до N-1).
from sklearn.preprocessing import LabelEncoder
# Данные
colors = ['красный', 'синий', 'красный', 'зелёный', 'синий']
# Создаём и применяем
le = LabelEncoder()
encoded = le.fit_transform(colors)
print("Оригинал:", colors)
print("Закодировано:", encoded)
print("Классы:", le.classes_)Результат:
Оригинал: ['красный', 'синий', 'красный', 'зелёный', 'синий']
Закодировано: [2 0 2 1 0]
Классы: ['зелёный', 'синий', 'красный']Совет:
LabelEncoderудобен для целевой переменной (y). Для признаков с несколькими категориями лучше использоватьOneHotEncoder.
Где использовать LabelEncoder
Для целевой переменной (y)
В задачах классификации целевая переменная часто задана текстом (например, «Yes»/«No»). LabelEncoder превращает её в 0/1 :
from sklearn.preprocessing import LabelEncoder
y = ['Yes', 'No', 'No', 'Yes', 'Yes']
le = LabelEncoder()
y_encoded = le.fit_transform(y)
print(f"Целевая переменная: {y_encoded}")
print(f"Классы: {le.classes_}") # ['No', 'Yes']Для порядковых признаков
Если категории имеют порядок («Low», «Medium», «High»), LabelEncoder сохранит этот порядок в числах:
sizes = ['M', 'L', 'S', 'M', 'XL']
le = LabelEncoder()
sizes_encoded = le.fit_transform(sizes)
print(sizes_encoded) # [1 2 0 1 3]
# S->0, M->1, L->2, XL->3 — порядок сохраняетсяСовет: Для порядковых данных
LabelEncoderподходит, потому что числа отражают естественный порядок.
OneHotEncoder — бинарное кодирование
OneHotEncoder создаёт отдельный бинарный столбец (0 или 1) для каждой категории.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# Данные
colors = pd.DataFrame({'Цвет': ['красный', 'синий', 'красный', 'зелёный']})
# Создаём и применяем
ohe = OneHotEncoder(sparse_output=False)
encoded = ohe.fit_transform(colors)
print("Оригинал:")
print(colors)
print("\nЗакодировано (One-Hot):")
print(encoded)
print(f"Категории: {ohe.categories_}")Результат:
Оригинал:
Цвет
0 красный
1 синий
2 красный
3 зелёный
Закодировано (One-Hot):
[[0. 0. 1.]
[0. 1. 0.]
[0. 0. 1.]
[1. 0. 0.]]
Категории: [array(['зелёный', 'синий', 'красный'], dtype=object)]Совет: Параметр
sparse_output=Falseвозвращает обычную матрицу (не разреженную). Это удобно для просмотра.
Сравнение OneHotEncoder и LabelEncoder
| Характеристика | LabelEncoder | OneHotEncoder |
|---|---|---|
| Результат | Одна колонка с числами | N колонок с 0/1 |
| Порядок | Создаёт искусственный порядок | Не создаёт порядок |
| Размерность | Не увеличивает | Увеличивает (N категорий) |
| Когда использовать | Целевая переменная, порядковые данные | Номинальные признаки |
| Пример | ['No','Yes'] → [0,1] | ['красный','синий'] → [[1,0],[0,1]] |
Совет:
OneHotEncoderне создаёт ложного порядка между категориями, что критично для номинальных данных.
Полный пример: подготовка данных для модели
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
from sklearn.linear_model import LogisticRegression
# 1. Создаём данные
data = {
'Город': ['Москва', 'СПб', 'Казань', 'Москва', 'СПб', 'Казань'],
'Возраст': [25, 30, 22, 35, 28, 40],
'Подписка': ['Yes', 'No', 'Yes', 'Yes', 'No', 'No']
}
df = pd.DataFrame(data)
print("Исходные данные:")
print(df)
# 2. Разделяем X и y
X = df[['Город', 'Возраст']]
y = df['Подписка']
# 3. Кодируем категориальные признаки (OneHotEncoder)
ohe = OneHotEncoder(sparse_output=False)
X_encoded = ohe.fit_transform(X[['Город']])
X_encoded_df = pd.DataFrame(X_encoded, columns=ohe.get_feature_names_out(['Город']))
# Объединяем с числовыми признаками
X_final = pd.concat([X_encoded_df, X[['Возраст']].reset_index(drop=True)], axis=1)
print("\nПризнаки после OneHotEncoder:")
print(X_final)
# 4. Кодируем целевую переменную (LabelEncoder)
le = LabelEncoder()
y_encoded = le.fit_transform(y)
print(f"\nЦелевая переменная (закодирована): {y_encoded}")
print(f"Классы: {le.classes_}")
# 5. Обучаем модель
X_train, X_test, y_train, y_test = train_test_split(
X_final, y_encoded, test_size=0.3, random_state=42
)
model = LogisticRegression()
model.fit(X_train, y_train)
accuracy = model.score(X_test, y_test)
print(f"\nТочность модели: {accuracy:.2%}")Когда использовать альтернативы
Проблема высокой размерности
Если в категориальном признаке 100+ уникальных значений, OneHotEncoder создаст 100 колонок — это много памяти. Рассмотри:
- BinaryEncoder — кодирует категории в битовые строки (экономит память)
- Target Encoding — заменяет категорию на среднее целевой переменной (требует аккуратности)
Для деревьев решений
Random Forest и Gradient Boosting не требуют OneHotEncoder — они хорошо работают с LabelEncoder.
# Для деревьев можно использовать просто LabelEncoder
for col in ['Город', 'Пол']:
X[col] = LabelEncoder().fit_transform(X[col])Задачи для закрепления
Задача 1. Что такое категориальные данные и какие они бывают двух типов?
Задача 2. Какой метод кодирования подходит для целевой переменной (y)?
Задача 3. Создай OneHotEncoder для признака ['A', 'B', 'C', 'A', 'B'].
Задача 4. В чём проблема использования LabelEncoder для номинальных признаков?
Задача 5. Когда OneHotEncoder может быть неэффективным?
Ответы:
Задача 1.
Категориальные данные — данные, принимающие ограниченное число значений. Бывают номинальные (без порядка) и порядковые (с порядком).
Задача 2.
LabelEncoder. Он преобразует текстовые метки в числа 0, 1, 2.
Задача 3.
from sklearn.preprocessing import OneHotEncoder
import numpy as np
data = np.array(['A', 'B', 'C', 'A', 'B']).reshape(-1, 1)
ohe = OneHotEncoder(sparse_output=False)
encoded = ohe.fit_transform(data)
print(encoded)Задача 4.
LabelEncoder создаёт искусственный порядок (A=0, B=1, C=2). Модель может решить, что C > B > A, хотя для номинальных данных это не так.
Задача 5.
При большом количестве уникальных категорий (100+). OneHotEncoder создаёт 100 колонок, что увеличивает память и может ухудшить работу модели.
Нюансы и подводные камни
Unseen categories в тестовых данных
Если в тестовых данных появится категория, которой не было в обучении, OneHotEncoder по умолчанию выдаст ошибку. Решение: используй параметр handle_unknown='ignore'.
ohe = OneHotEncoder(handle_unknown='ignore', sparse_output=False)Дамми-ловушка (Dummy Trap)
При использовании OneHotEncoder без drop='first' может возникнуть мультиколлинеарность. Решение: drop='first' убирает один столбец.
ohe = OneHotEncoder(drop='first', sparse_output=False)LabelEncoder для нескольких колонок
LabelEncoder не предназначен для нескольких колонок одновременно. Для этого лучше использовать OrdinalEncoder:
from sklearn.preprocessing import OrdinalEncoder
encoder = OrdinalEncoder()
X_encoded = encoder.fit_transform(X[['Город', 'Пол']])Частые ошибки и как их избежать
Ошибка 1: LabelEncoder для номинальных признаков
# Неправильно — создаёт ложный порядок
X['Город'] = LabelEncoder().fit_transform(X['Город'])
# Правильно — используй OneHotEncoder
ohe = OneHotEncoder(sparse_output=False)
X_encoded = ohe.fit_transform(X[['Город']])Ошибка 2: OneHotEncoder для целевой переменной
# Неправильно — y становится матрицей
y_encoded = OneHotEncoder().fit_transform(y.to_frame())
# Правильно — используй LabelEncoder
y_encoded = LabelEncoder().fit_transform(y)Ошибка 3: Не разделил данные перед кодированием
# Сначала кодируем всё, потом разделяем (утечка данных)
ohe.fit_transform(X)
X_train, X_test = train_test_split(X)
# Сначала разделяем, потом кодируем
X_train, X_test = train_test_split(X)
ohe.fit(X_train)
X_train_enc = ohe.transform(X_train)
X_test_enc = ohe.transform(X_test)Шпаргалка
| Что нужно | Как пишется |
|---|---|
| LabelEncoder | LabelEncoder() |
| OneHotEncoder | OneHotEncoder(sparse_output=False) |
| Кодировать целевую переменную | le.fit_transform(y) |
| Кодировать признаки | ohe.fit_transform(X[['колонка']]) |
| Игнорировать новые категории | handle_unknown='ignore' |
| Убрать дамми-ловушку | drop='first' |
| Увидеть названия колонок | ohe.get_feature_names_out() |
Заключение
Сегодня мы научились:
- Различать номинальные и порядковые категориальные данные
- Использовать
LabelEncoderдля целевой переменной и порядковых признаков - Использовать
OneHotEncoderдля номинальных признаков - Избегать ошибок при кодировании
- Понимать, когда какой метод применять
Запомни главное правило:
Запомни главное правило:
LabelEncoder → для y (целевая переменная)
OneHotEncoder → для X (номинальные признаки)




