В этом посте мы будем обучать LSTM (Long-Short-Term-Network), который представляет собой тип RNN для классификации текстовых данных из обзоров Yelp. Во время работы над этим проектом я занялся проблемой уменьшения дисперсии в модели, поэтому цель этой публикации - показать, как обучить LSTM и как настроить модель для уменьшения дисперсии и повышения точности данных валидации.
Цель этого поста - продемонстрировать, как использовать LSTM для текстовых данных, поэтому предполагается предварительное знание моделей и рекуррентных нейронных сетей. Ссылки в нижнем разделе ссылок являются хорошей отправной точкой для ознакомления с темами.
Пост будет разделен на 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.
использованная литература
- Для этого поста я исследовал LSTM и RNN. Мне очень пригодился следующий пост: http://colah.github.io/posts/2015-08-Understanding-LSTMs/
- Я нашел несколько полезных статей по Machine Learning Mastery, а также код. Я рекомендую эти сообщения как полезные ссылки для улучшения ваших моделей и получения результатов:
- Подготовка данных для LSTMS: https://machinelearningmaster.com/clean-text-machine-learning-python/
- Определение модели LSTM: https://machinelearningmastery.com/sequence-classification-lstm-recurrent-neural-networks-python-keras/
- Как диагностировать переобучение: https://machinelearningmastery.com/diagnose-overfitting-underfitting-lstm-models/
- Контрольные точки моделей Кераса: https://machinelearningmaster.com/check-point-deep-learning-models-keras/