Вступление

Раньше я сталкивался с алгоритмами машинного обучения для решения различных задач, таких как прогнозирование обменного курса денег или классификация изображений. Недавно мне пришлось работать над проектом классификации текстов, и я прочитал много литературы по этой теме. Случай с НЛП (обработка естественного языка) захватывающий. Когда вы начали задумываться, то поняли, что это не так просто, и до классификации остается вопрос:
Как, черт возьми, алгоритм может читать слова?. Одно из решений - преобразовать слова в векторы, чтобы получить их числовое представление. Это решение далеко не новое, и несколько лет назад в статье был представлен неконтролируемый алгоритм Google Word2Vec: Эффективное оценивание представлений слов в векторном пространстве (Миколов и др., 2013). Можно найти много документации по этому поводу, но цель этой статьи - подробно рассказать от А до Я, как построить алгоритм машинного обучения для классификации текста. Я продемонстрирую, как использовать Word2Vec с предварительно обученным набором данных новостей Google и как обучить его самостоятельно с вашими данными. Затем я продемонстрирую две техники; один - использовать средние значения слов в документе, а другой - сохранять данные такими, какие они есть, которые содержат больше информации, но это немного сложнее и требует больше времени на обучение. Так что это зависит от вас, что, по вашему мнению, лучше в вашем случае и с вашими данными.

1 НАМ НУЖНО ИМПОРТИРОВАТЬ ДАННЫЕ В первую очередь

На этом этапе убедитесь, что папка с вашими отзывами находится в той же папке, что и записная книжка.

Данные, которые я использовал, - это обзоры фильмов, которые можно найти здесь: Movie reviews. Я взял набор данных полярности предложений v1.0. Я взял набор данных полярности предложений v1.0. Я выбрал эти, потому что могу сравнить свои результаты с работой Сверточные нейронные сети для классификации предложений (Юн Ким, 2014). Преимущество этой статьи состоит в том, чтобы представить нейронную сеть для этого набора данных, но она сравнивает ее результат с другими алгоритмами в таблице 2, что действительно интересно, потому что у нас есть много алгоритмов из разных документов для сравнения наших результатов.

Извлеките файл, который вы скачали со ссылкой.
Итак, теперь у нас есть одна папка с именем rt-polaritydata и два файла в ней с именами Rt-polarity.neg и rt-polarity.pos (соответственно, отрицательные и положительные отзывы). Наша задача здесь будет заключаться в том, чтобы поместить все данные в фреймы данных pandas для их анализа. Начните конвертировать их в файлы CSV.

Теперь мы создаем «ярлыки» для наших данных: 1 означает положительный отзыв, а 0 - отрицательный.

Теперь результат должен быть следующим

Ладно, вроде здорово! Теперь у нас есть каждый отзыв в нашем фреймворке pandas под названием «reviews» с определенной меткой (1 для положительного отзыва, 0 для отрицательного).

2 ИСПОЛЬЗОВАНИЕ Word2Vec, ЧТОБЫ УЗНАТЬ РАССТОЯНИЕ ПОДОБИЯ МЕЖДУ НАШИМИ СЛОВАМИ

Word2Vec - хорошая модель нейронных сетей, используемых для встраивания слов. Он используется в основном для определения контекста подобия слов. Мы обучим модель на наших данных иметь расстояние между всеми нашими словами, чтобы увидеть, какие из них семантически близки друг к другу. Есть и другие модели, но я выбрал именно эту по 2 причинам:

  1. Именно его использовал Юн Ким в своей статье.
  2. Это модель, разработанная Google, кажется, она полностью рекомендована, документацию можно легко найти, и эта статья: Эффективная оценка представлений слов в векторном пространстве (Миколов и др., 2013) хорошо объясняет весь процесс.

2.1 Токенизация

Теперь ваш фрейм данных должен выглядеть так

Для обучения важно, чтобы каждый отзыв был представлен в виде списка слов, как в столбце «жетоны».

2.2: Используйте предварительно обученный набор данных новостей Google

Во-первых, вам необходимо скачать набор данных здесь: Набор данных новостей Google.
Затем распакуйте его в свою папку. Я извлекаю его в подпапку с названием модель.

Это так просто! Теперь у вас есть модель с именем «w2v_model», которая обучена и содержит каждое слово в наборе данных, представленное в виде векторов.

2.2.1 Обучение модели на ваших данных

Вы также можете обучить модель на своих личных данных. Однако я не рекомендую этот метод для небольших документов, потому что Word2Vec не сможет правильно уловить контекст ваших слов и не даст удовлетворительного результата. Я проверил его на своих данных для этой статьи, и результаты были заметно лучше с предварительно обученным Google Word2Vec. На другом наборе данных со средним значением 200 слов на документ он был более надежным и в некоторых случаях показал даже лучший результат, чем предварительно обученная модель.

Разделим работу на 3 этапа

  1. Word2Vec(). Инициализировать модель со всеми ее параметрами
  2. .build_vocab() Создайте словарный запас из последовательности предложений
  3. .train() Обучаем нашу модель

2.3 Результаты

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

  1. кино
  2. художественная литература
  3. хороший

По слову «хорошо» я получил следующие результаты.

Эти результаты получены с помощью предварительно обученного набора данных новостей Google.

Однако мы можем видеть, что модель не идеальна и не отражает семантику слов, потому что у нас есть [отличный, плохой, потрясающий, достойный]. Это может быть проблемой, потому что хорошее здесь «семантически» близко к плохому. На самом деле их можно использовать в одном контексте, но их значение не одно и то же.

2.5 Немного визуализации ДАННЫХ

Выше представлен график из 10 000 слов нашего набора данных. Те, кто семантически близки, находятся на карте рядом друг с другом. Я использовал боке, чтобы сделать карту динамичной, мы можем взаимодействовать с ней, и вы можете навести указатель мыши на точку, чтобы увидеть слово, которое ей соответствует.
Теперь мы можем ясно видеть отношения между всеми словами, и какие из них являются близкими или далекими.

3 НЕМНОГО РАБОТЫ НАД ДАННЫМИ

3.1 Обучающий тестовый сплит

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

3.2 Построение векторов

Здесь мы используем TfidfVectorizer из sklearn. Эта функция отражает силу слова в документе.
Мы используем строку tfidf = dict(zip(vectorizer.get_feature_names(), vectorizer.idf_)), чтобы поместить все слова в вектор с именем tfidf, как вы можете видеть чуть выше, если выполняете ее.
Это был совет, который я нашел в этом замечательном блоге Ахмеда БЕСБЕСА. Это действительно интересно и заслуживает того, чтобы его прочитали.

Теперь, просто для развлечения и визуализации, я использовал WordCloud, чтобы изобразить 100 самых важных слов из имеющегося у нас словаря. Мы можем видеть такие слова, как пьеса, фильм, сцена и история, которые, очевидно, важны для набора данных о кинокритиках.
Я использовал другой блог Ахмеда БЕСБЕСА, чтобы использовать эту библиотеку.

Теперь мы построим функцию, которая будет вычислять «среднее» для данного критика. Наша w2v_model дала нам, какие слова близки друг к другу, поэтому для каждого из них мы умножаем их на их важность в «словаре»: w2v_model[word].reshape((1, size)) * tfidf[word].
Примечание: мы используем функцию изменения формы, потому что мы делаем это для каждого текста нашего корпуса, так как, например, у нас есть 8529 текстов в X_train, если мы применим к нему эту функцию, у нас будет двумерная матрица форма (8529,300).

  1. 8529 - количество текстов в нашем корпусе
  2. 300 обозначает размер вектора, созданного Word2Vec.

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

Расчет можно возобновить следующим образом:

Где :

  1. n - количество слов в тексте
  2. Wi - вектор Word2Vec размером 300 для данного слова i
  3. Ti - значение tfidf для данного слова i

Теперь применим эту функцию к нашим данным.
Итак, как я уже сказал, buildWordVector имеет два аргумента: токены и размер. Размер равен 300 из-за модели word2vec, у нас есть форма 300. Для токенов он будет увеличиваться в цикле, чтобы покрыть все 8529 текстов нашего обучающего корпуса и 2133 нашего тестового корпуса.

4 ПЕРВАЯ НЕЙРОННАЯ СЕТЬ

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

4.1 Построить нейронную сеть

Вот характеристики этого простого классификатора.

  • Количество плотных слоев: 2
  • Функция активации: relu и sigmoid для последнего плотного слоя.
  • Прекращение обучения: 0,7
  • Оптимизатор: Adadelta
  • Потеря: двоичная кросс-энтропия

4.2 Обучение нейронной сети

Теперь мы обучаем нашу нейронную сеть на наших обучающих данных с batch_size, равным 50, и с 20 эпохами.
Больше эпох вроде не меняет точности. Может быть полезно выполнить поиск по сетке с другим размером batch_size и количеством эпох, чтобы увидеть лучшие параметры.

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

В итоге мы имеем точность обучения 0,8342 и точность теста 0,7286. Это неплохо, и важно отметить, что у нас не так уж много переобучения.

5 КОНВОЛЮЦИОННАЯ НЕЙРОННАЯ СЕТЬ

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

5.1 Построить нейронную сеть

Сначала мы пытаемся найти все параметры для построения нашей нейронной сети. Это будет CNN, но вместо того, чтобы кормить его средним значением всех векторов слов в предложении, мы дадим ему все векторы слов в данном предложении.
Кроме того, немного меняется структура, в каждом слое появляется больше нейронов.

Наша нейронная сеть аналогична той, которую построил Юн Ким (2014), которую я описал выше.

  • Количество сверточных слоев: 3
  • Количество плотных слоев: 2
  • Количество карт функций: 128 на свертку.
  • Функция активации: relu и sigmoid для последнего плотного слоя.
  • Размер фильтра: 3, 4 и 5.
  • Прекращение обучения: 0,5
  • Оптимизатор: Adadelta
  • Потеря: двоичная кросс-энтропия

Есть несколько отличий между этим CNN и тем, что использовал Юн Ким:
1. У него был только 1 плотный слой
2. Он никогда не использовал сигмовидную проекцию
3. Он использовал 100 карт характеристик на свертку вместо 128

Однако у меня были лучшие результаты с этими небольшими изменениями, поэтому я оставил их такими.

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

Теперь мы создаем входные данные для поезда и тестирования, которые будем использовать в нашей CNN. Для каждого документа, в котором количество слов меньше максимального, мы заполняем цифрой «0». Это не меняет наших результатов, потому что CNN распознает шаблоны, и шаблон все равно будет таким же, как бы он ни был в определенный момент или в другой. Например, для изображения это означает, что если изображение меньше других, мы добавим к нему черные границы. Это не изменит изображения.

5.2 Определение CNN

Результат резюме должен быть следующим:

И давайте проведем тренировку из 10 эпох и снова размер партии из 50!

В конце 10 эпох у нас есть точность для обучающего набора 0,915 и 0,7768 для набора для тестирования. У нас есть небольшое переоснащение, и потеря валидации довольно нестабильна, но результаты здесь. Я тренировал его с большим количеством эпох, но, похоже, это лучшее, что мы могли иметь.

6. ВЫВОДЫ

Мы ясно видим, что CNN лучше подходит для этой задачи, и с другими моими фреймами данных я лично получил те же результаты.
Но в нем все же есть неудобство, он намного глубже, имеет намного больше параметров и требует больше времени на обучение. Для этого небольшого набора данных разница не так уж и важна, но мне пришлось обучить его на данных для моей работы, а обучение простому классификатору заняло 13 минут, тогда как CNN заняло 5 часов! Так что вам решать, какой из них вы хотите использовать.
Эти два классификатора по-прежнему показывают хорошие результаты, и я заметил, что чем больше у них данных и чем важнее длина документа, тем они лучше. Для набора данных из 70 000 данных и максимальной длины документа 2387 точность моего теста составила 0,9829, так что это очень обнадеживает!

7 ПЕРСПЕКТИВ

У меня есть две основные идеи, чтобы попытаться добиться лучших результатов. Во-первых, с первым классификатором мы могли бы использовать другую более сложную нейронную сеть, например рекуррентную нейронную сеть (CA-RNN: Использование контекстно-ориентированных рекуррентных нейронных сетей для моделирования схожести предложений (Чен, Ху и др., 2018). ) или Attentional Network, которые начинают использоваться сейчас (Hierarchical Attention Networks for Document Classification (Yang & al., 2016)).
Вторая идея касается встраивания слова, в 2018 году Google показал новый модель под названием BERT (BERT: предварительное обучение глубоких двунаправленных преобразователей для понимания языка (Девлин, Чанг и др., 2018)), которые имеют преимущество в использовании сегментации токенов. Например, если у нас есть слово археолог в наших данных, он может запомнить слово археология, и когда появится такое слово, как археология, он будет знать, что это связано с археологом, тогда как word2Vec просто проигнорирует слово, которое не знать.