Анализ главных компонентов при встраивании предложений

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

В Конкурсе актуарных убытков на Kaggle мы должны спрогнозировать стоимость страховых выплат в связи с травмами рабочих. Нам дается ряд очень классических характеристик, таких как возраст, заработная плата, количество детей-иждивенцев и т. Д., А также краткое текстовое описание характера и обстоятельств аварии, и мы должны предсказать окончательную стоимость этого требования.

Специфика этой работы заключается, во-первых, в том, что я выполнил ее сквозной на GPU с RAPIDS, библиотеки которых cuPY, cuDF и cuML позволяют воспроизводить все Numpy, Pandas или Scikit. -Изучите манипуляции на GPU; и во-вторых, я пытаюсь извлечь информацию о числовой цели (окончательная стоимость претензии) на основе только текстовых данных (описание травмы).

Настройка среды

Вложения предложений будут сгенерированы с помощью преобразователя PyTorch, а затем они будут обработаны анализом основных компонентов на RAPIDS.

Во-первых, вы должны убедиться, что у вас установлена ​​среда RAPIDS (я рекомендую версию 0.18). Я использую ZBook Studio с NVIDIA RTX5000, который поставляется с Z от HP Data Science Software Stack, поэтому у меня уже все установлено и правильно настроено (я знаю, что создание сред и управление ими может быть проблемой). Если вы работаете на ядре Kaggle, обязательно добавьте репозиторий RAPIDS и установите RAPIDS со следующим:

Затем установите репозиторий предложений-трансформеров и другие требования:

Все готово!

Чтение и обработка данных

Прочитать данные и извлечь описание претензии довольно просто. Более того, текстовые данные уже очищены, нам нужно только преобразовать их в нижний регистр (большинство производных Bert построены для текстовых данных без регистра).

Необработанные вложения из преобразователя предложений Torch

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

Трансформаторы предложений - это просто обычные трансформеры, о которых слышали все, кто вовлечен в НЛП, то есть, изначально Bert и все его производные: другие языки (CamemBert и т. Д.), Надежные (RoBerta) и легкие (DistilBert, DistilRoberta). версии. Единственная разница заключается в задачах, которым они обучены, которые включают обработку текста на уровне предложения, а не на уровне исходного слова. Их использование очень широко:

Модель, которую я выбрал для вычисления своих вложений, называется DistilRoBerta для оценки перефразирования.

Почему я выбрал модель перефразирования? Что ж, это сугубо личный выбор, смело используйте другую модель. Я просто подумал, что эта модель будет лучше улавливать общее значение предложения, не уделяя слишком много внимания выбору одного слова или синонима (в основном это и есть перефразирование), и это было моей целью с тех пор, как описание очень краткое и функциональное.

На самом деле это довольно большая модель, несмотря на то, что она является более легкой версией оригинальной Roberta: у нее все еще есть более 82 миллионов обучаемых параметров ...

Общий процесс получения вложения предложений на самом деле очень прост.

Во-первых, для каждого входного предложения вы должны сопоставить слова с их идентификаторами в словаре, используемом моделью, добавив токены ‹START› и ‹END›.

В конце концов, мы должны добавить токены ‹PAD› в конце, чтобы наш ввод соответствовал максимальной длине входной последовательности модели.

В моем случае максимальная длина последовательности исходной модели составляла 128, но максимальная длина моих входных данных (включая токены ‹START› и ‹END›) была 21, поэтому я установил эту максимальную длину последовательности равной 25 для безопасных целей обобщения. Это сэкономит нам много ненужных вычислений и времени вычислений.

Затем наша модель отображает входные идентификаторы в соответствующие им вложения токенов, которые представляют собой конкатенацию вложений слов, встраиваний позиций (мы первое, второе, третье слово?) И встраивания типов токенов (мы нормальное слово? A ‹START ›?). Наконец, мы просто нормализуем черты.

Теперь для каждого токена у нас есть начальное тензорное представление, которое мы передаем в кодировщик (я не буду здесь вдаваться в подробности, подробнее см. Статью Внимание - все, что вам нужно Знакомство с архитектурой кодер-декодер).

Кодер выводит 768-мерное тензорное представление любой входной последовательности. Что нам теперь с этим делать? Прежде всего, мы должны убедиться, что эти вложения будут полезны при подаче в регрессионную модель для прогнозирования окончательной суммы требования. В идеале это означало бы наличие ортонормированных осей с координатами, несущими большую объяснимую силу и позволяющими кластеризацию типов аварий или тяжести травм.

К сожалению, это далеко не так: действительно, исходная модель перефразирования Роберта была обучена на огромном и эклектичном наборе данных, тогда как наши входные данные имеют большое семантическое сходство, все вращающееся вокруг здоровья.

Для всех 768 тусклых значений моих нормализованных встраиваний предложений я вычислил дисперсию координат между моими 90_000 текстовыми образцами. На этой гистограмме видно, что большинство дисперсий очень низкое: для справки дисперсия U ([0,1]) составляет 1/12 = 0,0833.

Поэтому мои представления, вероятно, будут очень похожими.

Обработанные вложения из PCA с RAPIDS

На данный момент мы сталкиваемся с двумя проблемами: во-первых, вложения слишком велики (768 компонентов, когда у нас есть только 12 дополнительных обучающих функций), и мы бы предпочли, чтобы они принесли больше объяснимости и разделимости по отношению к нашей цели, конечной понесенные претензионные расходы.

PCA используется для разведочного анализа данных и для создания прогнозных моделей. Он выполняет уменьшение размерности, проецируя каждую точку данных только на несколько первых основных компонентов, чтобы получить данные более низкой размерности, сохраняя при этом как можно больше вариаций данных. Первый главный компонент может быть эквивалентно определен как направление, которое максимизирует дисперсию прогнозируемых данных. Затем второй компонент - это направление, ортогональное первому, которое максимизирует дисперсию данных и т. Д.

Эта процедура итеративно дает ортонормированные векторы в порядке убывания степени объяснимости дисперсии данных. Проецирование данных на первые n компонентов приводит к уменьшению размерности, проецируя их в R ^ n, сохраняя при этом как можно большую дисперсию данных.

Обратите внимание, что я выполнил анализ основных компонентов для всех встраиваний описаний утверждений, как из обучающих, так и из тестовых наборов данных, чтобы получить лучшее соответствие, которое подойдет для обоих наборов данных. На первый главный компонент приходится 7,6% общей дисперсии данных, на второй - 3,9%. В сумме они объясняют 11,5% вариабельности необработанных вложений.

Вот когда я попытался визуализировать проекции точек данных на этом 2-м пространстве, что меня поразило:

Разве это не мило? Из этого можно сделать несколько интерпретаций. Во-первых, мы очень четко видим ортогональные направления изменчивости. Во-вторых, похоже, что есть 2 кластера точек данных, частично сливающиеся для более низких значений на 2 осях.

Объяснимость цели

Основываясь на этом наблюдении, я задался вопросом, могут ли эти 2 кластера обеспечить предсказательную силу для цели, конечной суммы понесенных претензий. Поэтому я решил построить все проекции точек данных поездов (у нас, очевидно, нет целевых значений для тестовых точек…), раскрашивая их на основе целевого значения.

В этот момент я столкнулся с проблемой доступности: целевые значения явно ограничены снизу (стоимость заявки обязательно положительна), но не ограничены сверху, и некоторые из них были настолько экстремальными, что это заставляло мою цветовую карту взорваться, с большинством значений раздавлены до самого низа, а некоторые из них стремительно перерастают в верхние цвета. Поэтому я решил обезглавить мои данные самого верхнего квинтиля, чтобы получить более регулярное распределение.

Это был действительно впечатляющий результат, так как он демонстрирует возможности кластеризации на целевом объекте, обеспечиваемые анализом основных компонентов при встраивании текста, без каких-либо дополнительных функций. Здесь мы очень ясно видим, что правая половина сердца отвечает за более высокие затраты, в то время как левая половина покрывает более низкие требования.

Спасибо, что прочитали меня! Вы можете найти полный исходный код записной книжки Kaggle здесь.