Начнем с небольшого экскурса. Чтобы вы понимали суть добавляю небольшой словарик:
- Признаки - столбцы в таблице.
- Целевой признак - столбец, значения которого надо предсказать.
- Объекты - строки в таблице
В целом, это всё что вам следует знать для понимания текста ниже.
Осмотр данных
Чекаем информацию в данных и можем начинать.
Сделаем небольшой вывод: В таблице 309864 объекта и 11 признаков, из которых 6 признаков типа object, в признаках нет пропусков, что уже хорошо, но в дальнейшем нам надо будет поработать над таблицей, чтобы все признаки были количественными.
ВАЖНО! Я советую делать манипуляции по кодированию после того как вы разбили данные на на выборки. ПРИЧИНА! Кодирование переменных до разделения на обучающий и тестовый наборы может привести к "утечке данных". Это происходит потому, что кодирование во всем наборе данных, включая тестовый набор, может позволить модели запомнить целевые значения в тестовом наборе, которые не являются репрезентативными для реальных данных, с которыми модель еще не сталкивалась. Это может привести к чрезмерной подгонке и дать слишком оптимистичную оценку эффективности модели. Важно сначала разделить данные на обучающий и тестовый наборы, а затем выполнить кодирование, чтобы предотвратить утечку данных.
Вот тут и начинается теория о том, что можно сделать с данными, чтобы их подготовить для модели машинного обучения (Дальше буду говорить просто - "модель")
Теория "Подготовка категориальных признаков"
Я не буду разбирать все виды кодирования, а сделаю акцент, на часто используемые, с которых сам начинал.
Первое - Прямое кодирование (One-Hot Encoding, OHE).
Этапы работы:
- Мы передаем прямому кодированию категориальный признак через pd.get_dummies()
- Прямое кодирование берет все уникальные значения признака
- Каждое уникальное значение становиться отдельным признаком (столбцом), где в каждом объекте (строке), если было написано это уникальное значение, то ставиться 1, а если там было написано другое уникальное значение то 0.
Покажу на картинке как было и как стало, где появился 0, а где 1:
Код который реализовал вторую таблицу, которая теперь называется gearbox_ohe:
gearbox_ohe = pd.get_dummies(df['Gearbox']).astype('int')
gearbox_ohe = pd.concat([df, gearbox_ohe], axis=1).drop('Gearbox', axis=1)
Как видите вместо одного столбца появилось 2, потому что там было 2 уникальных значения: auto и manual. Но что нам делать если уникальных значений 50, 100, 300 или более, как например в столбце model.
Мы конечно обучить модель на большом количестве признаков, но это будет слишком ресурснозатратно. Надо придумать что - нибудь другое.
Второй вариант - Порядковое кодирование.
Тут надо запариться с кодом и вызвать еще одну библиотеку, но структура библиотеки настолько проста, что если вы выучите одну функцию, то дальше будет проще.
Работает порядковое кодирование просто:
- Оно смотрит на данные столбца;
- Присваивает каждому уникальному значению свой номер от 0 до n-1 (то есть, если уникальных значений 247, то диапазон будет от 0 до 246);
- Превращает столбец в набор чисел.
Давайте реализуем:
Так, ну у нас появилась проблема, OrdinalEncoder перевел всё в тип float при этом изменил целевой признак, на это не подходит, давайте доработаем.
Уже не плохо, правда OrdinalEncoder работает не по значимости признака, а по номеру символа, это значит, что все бренды отсортировались по алфавиту и только после этого ему будут давать номер. А что если у нас есть две категории Peugeot и Porsche. Для нас Porsche выше по приоритету, чем Peugeot, но OrdinalEncoder присваивает Porsche один (1), а Peugeot - ноль (0). хотя надо наоборот. В целом это больше проблема для линейных моделей.
Третий вариант - Собственное кодирование
Вообще когда много категорий (>10), можно написать собственный класс кодирования или же просто использовать функции. Я написал в виде класса и вот что у меня получилось.
Конечно он не идеален, но он уже может обрабатывать ваши столбцы по одному и возвращать обработанные. Тоже самое я сделал для столбца "Brand", теперь там обработанные значения. Вот небольшой отчет по итогу наших манипуляций:
Только не путайте volkswagen это необязательно число 0.308056, а jeep это не 1.222350. Мой способ является необратимым, то есть точно понять что содержала строка изначально понять нельзя. А вот One-Hot является обратимым, то есть вы сможете восстановить исходные данные.
Так закреплю сюда табличку, по данным с плюсами и минусами методов кодирования, которые использовал выше.
* Для OrdinalEncoder обратимость возможна только если сохранен .categories_
Особенности вашего метода:
- Хэширование:
Преобразует любые данные (не только строки) в числа
Теоретически возможны коллизии (разные строки → одинаковый хэш)
Нет сохранения исходного словаря - Нормализация:
Автоматически масштабирует значения к μ=0, σ=1
Полезно для алгоритмов, чувствительных к масштабу (SVM, нейросети) - Гибкость:
Работает с любыми типами данных (не только категориальными)
Не требует предварительного обучения на всех значениях
Рекомендации по выбору:
- Для линейных моделей → One-Hot (но осторожно с размерностью)
- Для деревьев → OrdinalEncoder или ваш метод
- Для текста/больших категорий → Ваш метод (хэширование экономит память)
- Если важна интерпретируемость → One-Hot (можно отследить исходные значения)