Хорошо известный инструмент уменьшения размерности может быть полезен для встраивания категориальных признаков.

Мы обсуждали некоторые из возможных способов внедрения категориальных функций: Kernel PCA и Spectral Encoding. Цель такого внедрения - отобразить категориальные признаки в векторы в низкоразмерном пространстве. Преимущество этого сопоставления в том, что оно значительно снижает переоснащение по сравнению с 1-горячим кодированием. Однако мы можем потерять информацию и затруднить обучение, если вложение выбрано неправильно. Чтобы повысить качество встраивания, мы используем информацию о сходстве категорий (которую мы можем установить a priori или путем вычисления подобия условного распределения вероятностей). Метод ядра PCA также использует распределение вероятностей категориальной переменной, тогда как спектральное кодирование - нет. Для полноты картины мы также будем использовать метод t-SNE и обсудим его преимущества и недостатки.

t-SNE означает t-распределенное стохастическое вложение соседей и изначально был предложен для визуализации данных большой размерности. В отличие от PCA, это нелинейный метод, и его цель - сохранить сходство между точками данных. Он вводит нелинейное преобразование исходных данных x в низкоразмерные векторы y и моделирует сходство между точками данных с помощью t-распределения Стьюдента:

Множество точек y находится путем минимизации KL-расхождения распределения Q от исходного распределения P:

Минимизацию можно выполнить с помощью градиентного спуска.

Чтобы продемонстрировать, как работает метод, мы будем использовать набор синтетических данных только с одной категориальной переменной Day of Week, где 0 - понедельник, а 6 - воскресенье:

array([ 23,  19,  15,  19,  22, 429, 473])

Здесь мы намеренно добавили больше данных за субботу и воскресенье, чтобы увидеть, как t-SNE будет учитывать распределение вероятностей исходных данных. Напомним, что на лапласовский метод не влияет распределение вероятностей исходных данных, в то время как PCA и PCA ядра зависят.

Функция ядра такая же, как в предыдущих примерах.

array([[1. , 0.9, 0.8, 0.7, 0.5, 0.1, 0.3],
       [0.9, 1. , 0.9, 0.8, 0.5, 0.1, 0.2],
       [0.8, 0.9, 1. , 0.9, 0.5, 0.1, 0.2],
       [0.7, 0.8, 0.9, 1. , 0.6, 0.1, 0.2],
       [0.5, 0.5, 0.5, 0.6, 1. , 0.7, 0.5],
       [0.1, 0.1, 0.1, 0.1, 0.7, 1. , 0.8],
       [0.3, 0.2, 0.2, 0.2, 0.5, 0.8, 1. ]])

Scikit-learn реализация t-SNE на самом деле хочет, чтобы я вместо этого предоставил метрическую функцию, поэтому мы преобразуем нашу матрицу ядра обратно в матрицу расстояний.

array([[-0.        ,  0.21072103,  0.4462871 ,  0.71334989,  1.38629436,  4.60517019,  2.40794561],
       [ 0.21072103, -0.        ,  0.21072103,  0.4462871 ,  1.38629436,  4.60517019,  3.21887582],
       [ 0.4462871 ,  0.21072103, -0.        ,  0.21072103,  1.38629436,  4.60517019,  3.21887582],
       [ 0.71334989,  0.4462871 ,  0.21072103, -0.        ,  1.02165125,  4.60517019,  3.21887582],
       [ 1.38629436,  1.38629436,  1.38629436,  1.02165125, -0.        ,  0.71334989,  1.38629436],
       [ 4.60517019,  4.60517019,  4.60517019,  4.60517019,  0.71334989, -0.        ,  0.4462871 ],
       [ 2.40794561,  3.21887582,  3.21887582,  3.21887582,  1.38629436,  0.4462871 , -0.        ]])

Сигма здесь - важный гиперпараметр, который необходимо настроить. Еще один важный гиперпараметр метода t-SNE - оценка недоумения, но в нашем случае ее можно либо оставить по умолчанию, либо установить на сигму.

В этом первом примере мы использовали t-SNE без ядра, что означает, что расстояние между всеми днями недели равно 1. Это то, что вы получите, просто используя 1-горячее кодирование. Обратите внимание, что вложения кажутся распределенными случайным образом, и в этом отличие от PCA, который даже при отсутствии ядра использует распределение вероятностей исходных данных для встраивания данных таким образом, чтобы максимизировать их линейную разделимость. Посмотрим, какие результаты мы получим, если воспользуемся функцией ядра:

Здесь результаты более значимы. С понедельника по четверг сгруппированы вместе, чтобы сохранить их сходство. Пятница, суббота и воскресенье находятся далеко друг от друга и от других дней. Интересно видеть, что пятница ближе к воскресенью, чем суббота.

Заключение и обсуждение

t-SNE - один из вариантов встраивания категорий. Как правило, t-SNE не обобщает (потому что он не может отображать неизвестные данные), но для категориальных характеристик это не имеет значения, потому что новые данные будут иметь одну из существующих категорий. Более серьезная проблема заключается в том, что он не будет работать без ядра, в отличие от PCA, который даст разумные результаты, даже если ядро ​​не указано. Как и Kernel PCA, он использует распределение вероятностей для сопоставления данных, хотя и другим способом. Если Kernel PCA пытается добиться гладкости в результирующем векторном пространстве, t-SNE больше заботится о сохранении подобия. Вероятно, это поможет вам решить, какой метод больше подходит для вашей модели.

Вы можете найти код этой истории в моем репозитории на github.