В DS-задачах часто встречаются категориальные признаки с очень высокой кардинальностью (в которых много уникальных значений): ID, URL, слова в тексте, теги и прочее. Прямое one-hot кодирование таких признаков, скорее всего, приведёт к огромным разреженным матрицам и быстро "взорвёт" размерность🤯
Но прежде чем объединять редкие категории в "другое" или просто отбрасывать их, стоит рассмотреть hashing trick - простой и масштабируемый способ кодирования категориальных признаков.
В чём идея алгоритма?
➡️ берём строковое значение (например, user_id),
➡️ пропускаем его через хэш-функцию,
➡️ берём остаток по модулю D - заранее заданного размера выходного вектора,
➡️ получаем индекс, в который кладём 1 (или другое значение, если это count/frequency).
🧐Кажется, что похоже на one-hot - но вот в чём ключевое отличие: мы не храним словарь всех уникальных значений и сами выбираем размерность пространства D.
🤷♂️ Из минусов: при таком подходе возможны коллизии - два разных значения могут попасть в одну и ту же ячейку. Это происходит случайно, и по смыслу такие значения нельзя считать похожими. Но коллизии - это осознанная плата за компактность🤷♀️
👍 Из плюсов: метод работает стабильно и хорошо масштабируется. Даже если вдруг появляется новая категория, она автоматически попадает в какую-либо ячейку без пересоздания маппинга. Это делает hashing trick особенно удобным в стриминге, real-time inference и онлайн-обучении. Кроме того, можно кодировать "перекрестные" (парные, тройные и т.п.) категориальные фичи.
💻 В sklearn уже есть готовая реализация этого приёма:
from sklearn.feature_extraction import FeatureHasher
# хэшер на 10 выходных фичей
hasher = FeatureHasher(n_features=10, input_type='string')
# пример категориальных данных
data = [
['user_1', 'item_42'],
['user_2', 'item_17'],
]
# собственно преобразование
X = hasher.transform(data)
Hashing trick - не волшебная кнопка, но отличный инструмент в арсенале. Особенно там, где важны скорость, масштабируемость и минимальное потребление памяти.
Успехов в оптимизации размерности!🌹
#classic_ml@data_easy