В большом текстовом корпусе связанные слова (синонимы и т. Д.) Имеют хороший шанс встретиться с похожим набором слов, например - Правила 1 «короля» и правила «королевы». Здесь король и королева, хотя и не могут быть заменены напрямую, похоже, имеют отношение, а именно, оба относятся к правителю. Эта гипотеза о тексте, созданном человеком, называется гипотезой распределения.

Возникает вопрос: как вы представите эту взаимосвязь и семантическое сходство в числовом виде? Enter, вложение слов. Вложения слов - это плотные векторные представления слов, так что слова, встречающиеся в аналогичном контексте, имеют более близкие векторные представления. Все векторное пространство - это представление скрытой семантики. Эти вложения слов дополнительно помогают выявить значение документов и предложений, что создает возможности для множества последующих задач, таких как анализ настроений и т. Д., Которые затем могут использоваться для подтверждения рыночных тенденций.

Есть множество способов генерировать вложения слов. Традиционные методы назывались частотными методами. Они включали такие методы, как TF-IDF, Bag of words и т. Д. Новые используют глубокое обучение. Модели глубокого обучения, основанные на прогнозировании, намного мощнее с точки зрения информации, которую они предоставляют, поэтому давайте рассмотрим их подробно. Двумя популярными и повсеместными моделями глубокого обучения являются модель скип-грамма и модель непрерывного мешка слов. Давайте реализуем оба варианта с нуля с помощью Pytorch. Но прежде чем мы это сделаем, кратко изложим обе модели прогнозирования.

Модель пропуска грамма

Модель пропуска грамматики, как следует из названия, для заданного слова (которое пропускается) использует аппроксиматор функции (например, нейронную сеть) для предсказания его контекста . Контекст заданного слова - это набор слов до и после него в текстовом корпусе. Сколько слов до и после - это гиперпараметр модели, который необходимо оптимизировать.

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

Чтобы сделать обучение сети более надежным, в архитектуру были предложены некоторые изменения, основанные на эмпирических наблюдениях за результатами обучения, тестирования и проверки. Вместо одного входного слова, предсказывающего несколько контекстных слов, делается упрощение, так что мы разбиваем каждую обучающую пару (target, context_words) на несколько (target, context) обучающие пары, чтобы каждый контекст состоял из одного старого слова. Итак, если у нас есть предложение, скажем: «Быстрая коричневая лиса перепрыгивает через ленивую собаку», некоторые из наших обучающих примеров будут такими: (коричневый, быстрый), (лисий, коричневый), (прыжки, лиса) и т.п.

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

Формат наших обучающих выборок: (X, Y), где X - наш input, а Y - наш ярлык. Мы делаем это, используя пары [(target, context), 1] в качестве положительных входных выборок , где target - это интересующее нас слово, а context - контекстное слово, встречающееся рядом с целью слово и положительный ярлык 1 указывает, что это контекстно релевантная пара. Мы также вводим пары [(target, random), 0] как отрицательные входные образцы, где target - снова наше интересное слово, но random - это просто случайно выбранное слово из нашего словаря, которое не имеет контекста или ассоциации с наше целевое слово.

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

Модель непрерывного мешка слов

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

Архитектура модели CBOW пытается предсказать текущее целевое слово (центральное слово) на основе слов исходного контекста (окружающих слов). Рассматривая простое предложение, «быстрая коричневая лиса перепрыгивает через ленивую собаку», это могут быть пары (context_window, target_word) где, если мы рассматриваем контекстное окно размера 2, у нас есть такие примеры, как ([quick, fox], brown), ([the, brown], quick), ([the, собака], ленивый) и так далее. Таким образом, модель пытается предсказать target_word на основе слов context_window.

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

Реализация

Давайте реализуем модели Skip-Gram и CBOW с использованием Pytorch, nltk и т. Д. Мы будем использовать более простой текстовый корпус, чем, скажем, необработанные данные социальных сетей. Здесь я выбираю корпус «Алиса в стране чудес», который присутствует в nltk как стандартный корпус, взятый из Project Gutenberg.

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

Как показано в Коде 1, у нас есть функция, которая заменяет все, что выходит за рамки обычного алфавита, пустой строкой. Затем удаляет пробелы вокруг него, берет нижний регистр и токенизирует строку. После этого он удаляет все стандартные стоп-слова, заданные nltk, и снова присоединяет предложение и возвращает его. Затем, после того, как мы используем стандартную карту функций python, сопоставляем каждое предложение в корпусе с его чистой версией, а также удаляем все предложения меньше чем В них 2 слова. Это показано в коде 2.

После этого мы кодируем каждое уникальное слово как число, используя код Code3. На данный момент у нас есть корпус закодированных данных, который нам придется изменить по-разному для CBOW и SkipGram.

Реализация CBOW

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

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

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

После определения сети мы обучаем ее по одному горячему закодированному вектору словаря, который представляет каждое целевое слово. Как показано в Code6.

Сгенерированные вложения можно увидеть на рисунке 3.

Реализация Skipgram

Как и в реализации CBoW, мы взяли предложение в числовой кодировке в качестве входных данных, а затем преобразовали их в (контекстные слова, целевое слово). Мы делаем то же самое для модели пропуска грамматики. Разница в том, что формат обучающей выборки в этом случае ([(цель, контекст), релевантность]). Это легко становится возможным с помощью модуля предварительной обработки последовательности keras. в котором есть функция для создания обучающих выборок. Это показано в Code7. Функция принимает закодированные предложения в качестве входных данных, размер окна для генерации выборок и размер словаря.

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

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

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

Ссылки:

[1] https://www.kdnuggets.com/2018/04/implementing-deep-learning-methods-feature-engineering-text-data-skip-gram.html

[2] https://arxiv.org/abs/1301.3781 (статья Миколова)

[3] https://nlp.stanford.edu/pubs/glove.pdf