Применение НЛП и нейронных сетей к сложной задаче обработки текста
Некоторые сайты электронной коммерции позволяют клиентам писать отзывы о своих продуктах, которые затем могут просматривать другие клиенты при рассмотрении вопроса о покупке продукта. Я знаю, что читал обзоры продуктов, написанные моими коллегами-покупателями, которые помогли мне понять, будет ли продукт соответствовать размеру, долго ли прослужит или будет содержать ингредиент, который меня беспокоит.
Что, если бы бизнес мог предсказать, какие отзывы будут полезны его клиентам? Может быть, они могли бы разместить эти обзоры первыми на странице, чтобы читатели могли быстрее получить самую лучшую информацию. Возможно, бизнес мог бы отметить, какие темы поднимаются в этих полезных обзорах, и пересмотреть описания своих продуктов, чтобы они содержали больше такой информации. Может быть, бизнес мог бы даже определить «супер рецензентов», пользователей, которые особенно хороши в написании полезных обзоров, и предложить им стимулы для обзора большего количества продуктов.
Используя большую коллекцию обзоров продуктов от Amazon, я обучил ряд моделей машинного обучения, чтобы попытаться определить, какие обзоры читатели оценили как полезные. Я пробовал случайные леса, логистическую регрессию, машину опорных векторов, сети GRU и сети LSTM, а также различные методы обработки естественного языка (NLP) для предварительной обработки моих данных. Оказывается, предсказать полезные отзывы довольно сложно, но не невозможно! Чтобы перейти непосредственно к коду, ознакомьтесь с моим репозиторием на GitHub. Чтобы узнать больше о том, как я это сделал, читайте дальше.
Набор данных
Вот что вам нужно знать о наборе данных:
- Это происходит от Amazon (через Kaggle), в частности, из отдела продуктов питания, который включает в себя не только продукты питания, но и кухонные гаджеты и корма для домашних животных.
- Он был собран в период с 2002 по 2012 год, поэтому он не совсем актуален, но я думаю, что в 2020 году мы еще можем многому научиться.
- В нем было более 500 000 отзывов, и после того, как я удалил дубликаты, осталось 393 579 отзывов.
- У читателей была возможность отметить отзыв как «полезный» или нет. Была также возможность минусовать отзывы, но она мало использовалась. Около 52% отзывов получили ноль «полезных» голосов, а остальные получили один или несколько «полезных» голосов.
- Помимо «полезности» и текста самого отзыва, в набор данных также записываются идентификатор продукта, идентификатор пользователя, отметка времени и звездный рейтинг (из 5), который автор обзора дал продукту.
Вот краткий обзор количества отзывов, общего количества токенов и уникальных токенов по классам:
Хотя полезных отзывов меньше, они содержат больше слов и уникальных слов, чем бесполезные.
Недоумение над предсказанием
Учитывая содержимое этого набора данных, у меня возникло два больших вопроса. Вопрос 1: Можно ли предсказать «полезность» по каким-либо признакам, кроме текста самих отзывов? Например, если бы полезные обзоры всегда включали 5-звездочный рейтинг или всегда писались одним и тем же набором рецензентов, это избавило бы меня от большого количества текстовых споров!
Как оказалось, нет: полезные отзывы нельзя предсказать, используя какие-либо другие функции в наборе данных или какие-либо из нескольких, которые я разработал сам. Полезные обзоры могут быть короткими, длинными, положительными или отрицательными; их могут писать как новички, так и опытные рецензенты; они могут быть о популярных или малоизвестных продуктах; и их словарный запас очень похож на бесполезные обзоры.
Вот график t-SNE выборки обзоров с акцентом на самих текстах. График t-SNE в основном выполняет анализ основных компонентов в наборе данных, сокращает все функции до 2 или 3 компонентов и отображает их так, чтобы вы могли видеть, как классы перекрываются (или не пересекаются). Этот график раскрывает кошмар: по крайней мере, в этих двух измерениях два класса много перекрываются.
Это подводит меня к вопросу 2: если нет быстрого способа предсказать полезность, как мне предсказать ее по тексту? Как я должен предварительно обрабатывать обзоры для моделирования? Какие модели стоит попробовать? Использование созданного человеком текста в качестве входных данных для прогностических моделей общеизвестно сложно, отчасти потому, что существует так много способов превратить текст в данные, а затем вам нужны довольно сложные модели для обработки этих данных. Что выбрать?
Принимая решение о том, как предварительно обрабатывать тексты обзоров, я хотел попробовать ряд методов, сосредоточившись на тех, которые казались наиболее многообещающими на этапе исследования моего проекта. Что касается моделирования, я хотел начать с моделей, которые проще и быстрее обучать, а затем перейти к самым сложным вариантам. Я надеялся, что первые несколько раундов тестирования помогут мне определить наилучший вариант предварительной обработки, а последние несколько раундов помогут мне отточить мою лучшую модель.
Фаза 1: В лес
Мой первый большой раунд экспериментов состоял из тестирования различных методов предварительной обработки на базовой модели Random Forest:
- Обработал текст как биграммы, затем обучил их Random Forest.
- Обработал текст как матрицу терминов-документов (базовая векторизация подсчета), затем обучил на этом случайный лес.
- Рассчитали векторы TF-IDF (термин частота-инверсия частоты документа), а затем прогнали их через случайный лес.
Все они выполнялись с точностью 54–55% на данных проверки, что лишь немного лучше, чем случайное угадывание, но, по крайней мере, не хуже, чем случайное угадывание! TF-IDF набрал наибольшее количество баллов, поэтому я решил попробовать настроить случайный лес, чтобы он работал еще лучше с векторами TF-IDF в качестве входных данных. Я пробовал следующее:
- Использовали поиск по сетке, чтобы определить наилучшее количество оценок и максимальную глубину дерева для использования.
- Удвоил длину векторов TF-IDF (т. е. создал намного больше входных данных), затем провел анализ основных компонентов (используя TruncatedSVD), чтобы выбрать ряд компонентов, которые объясняли бы 80% дисперсии в данные тренировки.
- Обучил окончательный Random Forest, используя все, что я создал на предыдущих двух шагах.
Все это дало модель, которая была адаптирована к обучающим данным (точность более 99%) и 57% точности по данным проверки, мой лучший результат на данный момент.
Но на 7 процентных пунктов лучше, чем случайное угадывание — это не так уж и много, поэтому я перешел к подходу трансферного обучения.
Фаза 2: снятие перчаток
Трансферное обучение включает в себя использование весов, рассчитанных чужой моделью, и включение их в вашу собственную. Это может быть действительно удобным способом извлечь выгоду из чьих-то инвестиций в обучение огромной модели, например, всей Википедии.
Вот тут-то и появляются вложения GloVe. Некоторые умные ребята из Стэнфорда обучили массивную модель для количественной оценки отношений между английскими словами в контексте. Я могу извлечь из этого пользу, собрав соответствующий вектор встраивания из GloVe для каждого слова в моем корпусе обзоров. Затем для каждого обзора я беру среднее значение всех векторов отдельных слов, чтобы создать новый вектор, представляющий весь текст обзора. Затем все векторы обзора можно передать модели для обучения или прогнозирования.
Я передал свои вложения GloVe трем моделям: случайному лесу, логистической регрессии и классификатору опорных векторов. Эти модели также показали точность в диапазоне 53–56% по данным проверки, причем Random Forest показал лучшие результаты. После некоторой дополнительной настройки я все еще получал точность проверки только 56%.
После всего этого мне очень хотелось увидеть, на что способна нейронная сеть.
Фаза 3: Ничего, кроме сетей
Известно, что модели «последовательность к последовательности» хорошо работают с текстовыми данными, поэтому я решил попробовать несколько различных архитектур нейронных сетей этого типа. Я был особенно заинтересован в том, чтобы эти сети вычисляли свои собственные вложения на лету; поскольку GloVe показал себя не так хорошо, я надеялся, что встраивание, основанное только на моем наборе данных, может быть лучшим выбором.
Взгляните на структуру моей базовой нейронной сети:
# Try again with more epochs, callbacks
import tensorflow as tf
embedding_size = 128
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Embedding(200000, embedding_size, input_shape=(100,)))
model.add(tf.keras.layers.GRU(25, return_sequences=True, input_shape=(100,)))
model.add(tf.keras.layers.GRU(25, return_sequences=True, input_shape=(100,)))
model.add(tf.keras.layers.GlobalMaxPool1D())
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(50, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(50, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(1, activation='relu'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
history = model.fit(X_train, y_train, epochs=50, batch_size=2048, validation_data=(X_val, y_val))
Это слой для расчета вложений, два слоя по 25 узлов Gated Recurrent Unit (GRU) в каждом, слой для объединения их выходных данных, два плотных слоя по 50 узлов в каждом (с отсевом 50% во избежание переобучения), а затем один узел, чтобы сделать окончательный прогноз для каждой выборки. Я также попробовал ту же архитектуру, но с узлами долговременной кратковременной памяти (LSTM) вместо GRU. В результатах не было существенной разницы, а ГРУ были немного быстрее, поэтому я решил продолжить настройку сети ГРУ с большими входными векторами и большим количеством периодов обучения.
Лучшая модель и результаты
В целом, моей лучшей моделью была последняя: сеть GRU достигла 59% точности данных проверки. В моем наборе данных с задержкой эта модель также показала точность 59%, что неплохо, учитывая сложность проблемы, которую она пытается решить.
Подобную модель можно использовать для сортировки отзывов по мере их отправки и перемещения тех, которые могут оказаться полезными, в начало очереди. Компания также может очистить свой веб-сайт для получения отзывов, отфильтровать полезные, а затем просмотреть их, чтобы узнать, что хотят знать потенциальные клиенты, чего нет в описаниях их продуктов. Аналогичным образом компания может определить авторов полезных отзывов и побудить их написать больше или изменить форму отправки отзыва, включив в нее советы по написанию более информативных отзывов (как это уже делают AirBnB, TripAdvisor и другие).
Если вы хотите увидеть весь мой проект о полезных обзорах в мельчайших подробностях, посмотрите код на GitHub. Спасибо за чтение!
Кросс-пост с сайта jrkreiger.net.