Пошаговое практическое введение в Python

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

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

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

Задание

Проще говоря, учитывая большое количество текстовых документов, мы хотим иметь возможность:

  1. Измерьте, насколько документы похожи друг на друга семантически.
  2. Используйте эту информацию для кластеризации документов на основе их сходства.

Что мы расскажем

Я понимаю, что это более длинный пост. Итак, прежде чем мы начнем, вот краткое описание всего, что мы рассмотрим:

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

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

Данные

Для обучения и тестирования наших моделей мы будем использовать набор данных 20Newsgroups. Этот набор данных состоит из около 18000 сообщений групп новостей по 20 различным темам:

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

Например, это будет означать, что вместо выбора rec.sport.baseball и rec.sport.hockey мы можем захотеть заменить один из них, скажем, soc.religion.christian. Здесь я решил использовать категории soc.religion.christian, sci.space, talk.politics.mideast и rec.sport.baseball.

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

В Python мы можем использовать sklearn для получения данных:

По сути, мы создаем два словаря с 4 ключами в каждом (т. Е. 4 категории). Каждый ключ содержит в качестве своего значения все документы, принадлежащие этой категории, где один словарь содержит учебные документы, а другой - тестовые документы. Кроме того, параметр remove=('headers', 'footers', 'quotes') удаляет из документов такие метаданные, как заголовки, нижние колонтитулы и цитаты, чтобы наши модели не переоснащались им.

Генерация векторов

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

Мы хотим иметь возможность измерить, насколько документы похожи друг на друга семантически.

Другими словами, мы хотим преобразовать наши текстовые документы в числовую векторизованную форму, которая позже может быть использована алгоритмом кластеризации для группировки похожих документов.

Doc2vec

Одним из алгоритмов генерации таких векторов является doc2vec [1]. Прекрасное введение в концепцию можно найти в статье Гиди Шпербер. По сути, doc2vec использует подход нейронной сети для создания векторных представлений фрагментов текста переменной длины, таких как предложения, абзацы или документы. Эти векторные представления имеют то преимущество, что они фиксируют семантику, то есть значение входных текстов. Это означает, что тексты, похожие по смыслу или контексту, будут ближе друг к другу в векторном пространстве, чем тексты, которые не обязательно связаны.

Doc2vec основан на другом алгоритме, называемом word2vec [2]. Как вы могли догадаться по названию, word2vec работает очень похоже на doc2vec, за исключением того, что вместо того, чтобы давать нам векторы документов, мы получаем векторы слов. Это означает, что такие слова, как «быстро» и «быстро» будут ближе друг к другу в векторном пространстве, чем, например, «Лондон». Более того, эти векторные представления можно использовать для выполнения простых векторных операций. Например, vector("King") - vector("Man") + vector("Woman") приводит к вектору, который больше всего похож на векторное представление «Королевы».

Для более глубокого знакомства с word2vec я рекомендую взглянуть на эту статью Кунг-Сян, Хуанг (Стив).

Обучение

Итак, теперь, когда у нас есть представление о том, что делает doc2vec, давайте посмотрим, как мы можем обучить модель doc2vec на наших данных. Большая часть следующей реализации вдохновлена ​​этим учебником, который я настоятельно рекомендую проверить.

Во-первых, нам нужно немного настроить наши необработанные данные, чтобы подготовить их к обучению.

Опять же, мы используем словари, чтобы отслеживать, какие документы к каким категориям принадлежат. Для обучения модели doc2vec учебные документы должны иметь форму TaggedDocument, что в основном означает, что каждый документ получает уникальный идентификатор, предоставляемый переменной offset.

Кроме того, функция tokenize() преобразует документ из строки в список строк, состоящий из слов документа. Он также позволяет удалить выбор игнорируемых слов, а также слов, превышающих определенную длину.

Стоп-слова - это обычно общие слова, которые не добавляют контекстного значения к фрагменту текста и, таким образом, удаляются. Вы заметите, что здесь я решил не удалять стоп-слова, так как в этом случае производительность была немного лучше.

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

В итоге мы получаем следующие переменные:

  • train_corpus: список готовых к обучению документов
  • cat_dict_test_clean: содержит токенизированные тестовые документы, организованные по категориям

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

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

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

Значение epochs определяет, сколько раз корпус обучения будет использоваться во время обучения. vector_size определяет размер результирующих векторов документов. Кроме того, любое слово, встречающееся реже, чем min_count, будет отброшено. Не вдаваясь в подробности, window используется во время обучения, чтобы определить, сколько слов включить в контекст данного слова при его проверке. Подробнее в разделе 2.2. из [1].

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

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

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

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

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

Первый из двух файлов, doc2vec_20Newsgroups_vectors.csv, содержит по одному предполагаемому вектору документа на строку, представленную в виде значений, разделенных табуляцией, где векторы отсортированы по категориям.

Второй файл, doc2vec_20Newsgroups_vectors_metadata.csv, содержит в каждой строке категорию соответствующего вектора в первом файле. Это может выглядеть примерно так:

talk.politics.mideast
talk.politics.mideast
.
.
.
talk.politics.mideast
rec.sport.baseball
rec.sport.baseball
.
.
.
rec.sport.baseball
sci.space
sci.space
.
.
.
sci.space
soc.religion.christian
soc.religion.christian
.
.
.
soc.religion.christian

Визуализация

Так почему же мы все равно сохраняем наши векторы и их метаданные в файлы? Что ж, теперь мы можем использовать эти два файла для визуализации сходства между нашими документами с помощью инструмента проектора TensorFlow. В инструменте проектора вы можете выбирать между различными методами уменьшения размерности, а именно t-SNE, PCA и настраиваемой маркировкой осей, чтобы представлять векторы в 2D или 3D пространстве.

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

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

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

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

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

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

Эта функция принимает в качестве параметров только что обученную модель doc2vec и два сравниваемых документа. В качестве меры схожести документов функция затем возвращает значение от 0 до 1, где чем больше значение, тем более похожи документы.

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

Оценка нашей модели

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

Первым делом мы создадим наборы пар документов для всех категорий. Более конкретно, учитывая наши четыре категории, которые мы обозначим через C₁, .., C₄, где каждая категория представляет собой набор документов, мы получаем следующие пары категорий:

  • (C₁, C₁), (C₁, C₂), (C₁, C₃), (C₁, C₄)
  • (C₂, C₂), (C₂, C₃), (C₂, C₄)
  • (C₃, C₃), (C₃, C₄)
  • (C₄, C₄)

Обратите внимание, что пары, такие как (C₃, C₄) и (C₄, C₃), эквивалентны при измерении косинусного сходства, и поэтому во избежание избыточности рассматривается только одна из двух комбинаций.

Пара (Ca, Cb) соответствует декартовому произведению набора, содержащего все документы в категории a, и набора, содержащего все документы в категории b. Более формально:

Теперь для каждой пары документов мы вычисляем схожесть документов. В результате для каждой пары категорий получается матрица значений от 0 до 1 (одно значение для каждой пары документов).

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

Помните, что мы судим о нашей модели не по тому, насколько похожи документы из одной категории, а по тому, насколько они похожи друг на друга, чем документы из других категорий. Таким образом, ценность, которую мы действительно ищем, заключается не только в том, насколько высоко среднее сходство, скажем, (C₃, C₃), но, скорее, насколько оно высоко относительно среднего сходства (C₁, C₃ ), (C₂, C₃) и (C₃, C₄).

Таким образом, учитывая наши четыре категории, остается четыре средних сходства на категорию; один для документов той же категории и три для документов разных категорий.

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

Более высокая средняя разница говорит нам, что модель способна распознать, что документы одной категории более отличаются от документов других категорий. Конечно, это может быть не всегда так, если документы одной категории действительно похожи на документы другой категории. Это может быть более заметно в таких категориях, как comp.os.ms-windows.misc и comp.windows.x, чем в comp.os.ms-windows .misc и soc.religion.christian, например.

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

Представление результатов в такой компактной форме делает более эффективным обучение нескольких моделей с разными гиперпараметрами и сравнение их производительности.

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

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

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

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

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

Резюме

Так что, возможно, пришлось много переварить. Вот краткое изложение всего, о чем мы говорили в этой статье:

  • Мы рассмотрели метод doc2vec, обычно используемый для создания векторных представлений текстовых документов.
  • Мы увидели, как подготовить наши данные и обучить модель doc2vec на Python с помощью Gensim.
  • Мы увидели, насколько полезным может быть визуализация наших векторов с помощью проектора TensorFlow.
  • Наконец, мы обсудили один из возможных способов оценки модели doc2vec, который позволяет эффективно сравнивать несколько моделей.

Спасибо, что остались! Будем рады услышать ваши отзывы и ответить на любые ваши вопросы.

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

[1] QV Le, T. Mikolov, Распределенное представление приговоров и документов (2014)
[2] T. Mikolov, K. Chen, G. Corrado, and J. Dean, Эффективная оценка слова Представления в векторном пространстве , (2013)