В этом посте мы будем обучать LSTM (Long-Short-Term-Network), который представляет собой тип RNN для классификации текстовых данных из обзоров Yelp. Во время работы над этим проектом я занялся проблемой уменьшения дисперсии в модели, поэтому цель этой публикации - показать, как обучить LSTM и как настроить модель для уменьшения дисперсии и повышения точности данных валидации.

Цель этого поста - продемонстрировать, как использовать LSTM для текстовых данных, поэтому предполагается предварительное знание моделей и рекуррентных нейронных сетей. Ссылки в нижнем разделе ссылок являются хорошей отправной точкой для ознакомления с темами.

Пост будет разделен на 3 части. Эти:

  1. Подготовка данных для обучения
  2. Определение модели и ее обучение
  3. Настройка модели и устранение отклонений

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

"УДИВИТЕЛЬНЫЙ!!!!!!!!!!!!!! ЛЮБЛЮ ЭТО МЕСТО!!!!!!! Все в меню выглядело так хорошо !! Цыпленок с чесноком был БОМБОЙ !!!!!! НЕОБХОДИМО ЕСТЬ В ЭТОМ МЕСТЕ !!! Я рекомендую сделать заказ заранее, прежде чем отправиться в путь! Становится очень занято !!! » - 5 звезд.

«Бургеры здесь очень большие. обязательно закажу башню с луковыми кольцами разделить… Молочные коктейли вкусные! Мой личный фаворит - ванильный. - 3 звезды.

«Еда очень мягкая - совсем не настоящая. предназначен для клиентов, которые никогда раньше не ели вьетнамскую кухню. Точно не вернусь! » - 1 звезда

Как мы видим, обзоры представляют собой простой текст на естественном языке с некоторыми сленговыми и идоматическими словами. С помощью LSTM мы попытаемся обучить модель, чтобы узнать настроения пользователя. Очень отрицательный отзыв должен отличаться от очень положительного. Чтобы скачать набор данных, вы можете перейти по ссылке на Yelp.com/dataset.

Начнем с кода. Для этого проекта необходимы следующие библиотеки:

Tensorflow, Keras, Numpy, Scipy, MatplotLib и SkLearn.

Подготовка данных

Первая часть проекта - это подготовка данных. Как мы видели в примерах выше, отзывы очень разные. Некоторые из них содержат символы, странные символы пунктуации, а некоторые даже содержат не буквенно-цифровые символы. Мы очистим их и сохраним наиболее релевантные строки и слова из отзывов. Сначала загрузим данные:

Давайте рассмотрим этот метод. При загрузке данных мы смотрим на 2 критерия. Во-первых, мы пропускаем все отзывы с 3 звездочкой, потому что они нейтральны и с трепетом предсказывают только положительные или отрицательные настроения. Второй критерий - поддержание равного количества положительных и отрицательных отзывов. Если вы загрузите данные напрямую, то заметите, что рецензий гораздо больше + обзоров, с разделением почти на 70% -30%. Мы хотим, чтобы наши тренировочные данные были одинаково сбалансированными. В приведенном выше коде мы читаем столько же num_total отзывов, что в данном случае составляет 75,000. Поскольку данные находятся в формате Json, мы также загружаем каждую строку с помощью модуля json.loads. Наконец, мы разделяем каждую строку на reviews и stars, чтобы получить X и Y.

Теперь для очистки данных делаем следующие шаги:

Удалите знаки препинания, удалите не буквенно-цифровые символы, разбейте каждый отзыв на массив слов, каждое слово в нижнем регистре.

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

Keras предоставляет модуль Tokenizer, который мы можем использовать для кодирования текстов. После преобразования текстов в последовательности мы можем получить word_index. Нам также нужен обратный словарь, так что давайте построим и его. После этого мы можем создавать закодированные обзоры, просматривая тексты и сопоставляя каждое слово со значением встраивания.

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

Кажется, что 20–40 слов - наиболее распространенная длина для обзоров, с меньшим количеством рецензий для длины 60, 80 и 100. 60 будет хорошим числом, чтобы ограничить слова. Ссылаясь на приведенный ниже код, мы будем использовать функцию pad_sequences из Keras, которая будет обрезать более крупные обзоры и дополнять меньшие обзоры нулями до максимального значения 60.

Отсюда получаем наши X и Y. Метки будут преобразованы в представление с горячим кодированием. Следующий шаг - перемешать данные. Поскольку мы загрузили отзывы, ограничив их равными + и отзывами, возможно, что данные не совсем рандомизированы. Мы будем использовать random.shuffle numpy, чтобы перетасовать X и Y одинаково.

После этого мы должны разделить обзоры на 3 раздела: обучение, разработка и тестирование. Данные обучения будут использоваться для обучения модели и составят большую часть данных 85%. Данные разработчика будут использоваться для проверки после каждого цикла обучения, они 8%, и отдельно от обучения, поэтому их не видно. Последний 7% - это данные тестирования, также невидимые и используемые для проверки того, что модель не переоснащена для обучения и разработки. Мы разделим их соответственно, как показано в приведенном выше коде.

Определение и обучение модели

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

Это первая модель, которую я тестировал, в которой я определил 2 LSTM слоев с 21_ нейроном в каждом и без регуляризации. С оптимизатором Adam модель была обучена с batch_size равным 128. После запуска модели я получил следующие результаты:

Как видно, модель быстро переоснастилась. Всего за 10 эпох точность обучения повысилась с 0.88 до 0.99, в то время как точность проверки стабильно оставалась на уровне 0.87. Разница в потерях еще более несопоставима. На самом деле точность проверки действительно хороша для обучения такой базовой модели, но мы должны иметь возможность ее улучшить.

Тюнинг модели

Затем я попытался добавить больше регуляризации, уменьшить общее количество нейронов и изменить скорость обучения на большее значение. Обученная модель была:

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

Обучение с использованием перчаток

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

Здесь можно использовать один алгоритм - Word2Vec. Чтобы прочитать об этом, я рекомендую прочитать следующий пост на Medium, который я написал ранее. Для этой модели я буду использовать альтернативный метод кодирования под названием GloVe, который генерирует аналогичные векторные представления. Вместо обучения модели внедрения с нуля, мы будем использовать здесь предварительно обученную модель. Предварительно обученные векторы можно получить из этого Стэнфордского проекта.

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

Используя карту слов и векторов, мы создадим матрицу вложений, которая сопоставит каждое из слов в нашем словаре с вектором для него. Итерируя по нему, мы построим матрицу вложений, индексируя векторы перчаток.

Еще одно замечание: вложения имеют размер 100 для каждого вектора, в то время как мы использовали векторы размера 60. Мы могли бы снова усечь и дополнить векторы здесь, но вместо этого установим максимальное значение 100. Это означает, что вам нужно будет заново создать закодированные обзоры, снова вызвать pad_sequences и переделать X на основе нового max_cap.

Переходя к модели, мы меняем только одно - слой Embedding. Мы добавляем параметры weights=[embeddings_matrix] и trainable=False, чтобы убедиться, что слой получает кодировки из векторов GloVe и не обновляет веса во время обучения. После тренировки получаю следующие результаты:

Результаты этой модели значительно улучшились. Прежде всего, мы решили проблему дисперсии, потому что модель больше не переоснащается по обучающим данным. После 30 эпох точность изменилась с 0.90 на 0.93, в отличие от предыдущих моделей, которые стреляли до 0.99 всего за 5–10 эпох. Кроме того, повысилась точность проверки, достигнув 0.92. Разница между точностью обучения и тестирования также очень мала, что показывает, что по мере повышения точности обучения улучшается и тестирование. Это хороший показатель того, что модель не переоснащена. Во-вторых, точность проверки намного выше, чем у предыдущих моделей, у которых максимальная точность не превышала 0.89. При большем количестве обучающих данных можно будет еще больше повысить точность.

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

Окончательная точность, полученная при тестировании этой модели, составляет: 0,9148. Для полных невидимых данных мы получаем 92% точности, показывая, что модель смогла правильно обобщить и спрогнозировать правильное мнение на основе данного обзора Yelp.

использованная литература