Понимание проектирования функций (часть 4)

Практический интуитивный подход к методам глубокого обучения текстовых данных - Word2Vec, GloVe и FastText

Новые, продвинутые стратегии для укрощения неструктурированных текстовых данных

Вступление

Работать с неструктурированными текстовыми данными сложно, особенно когда вы пытаетесь создать интеллектуальную систему, которая интерпретирует и понимает свободный естественный язык, как люди. Вам необходимо уметь обрабатывать и преобразовывать зашумленные, неструктурированные текстовые данные в некоторые структурированные векторизованные форматы, которые могут быть поняты любым алгоритмом машинного обучения. Принципы обработки естественного языка, машинного обучения или глубокого обучения, которые подпадают под широкий круг искусственного интеллекта, являются эффективными инструментами в этой сфере. Основываясь на моих предыдущих сообщениях, важно помнить, что любой алгоритм машинного обучения основан на принципах статистики, математики и оптимизации. Следовательно, они недостаточно умны, чтобы начать обрабатывать текст в исходной, нативной форме. Мы рассмотрели некоторые традиционные стратегии извлечения значимых функций из текстовых данных в Часть 3: Традиционные методы для текстовых данных. Я рекомендую вам проверить то же самое, чтобы вкратце освежиться в памяти. В этой статье мы рассмотрим более сложные стратегии разработки функций, которые часто используют модели глубокого обучения. В частности, мы рассмотрим модели Word2Vec, GloVe и FastText.

Мотивация

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

Недостатки традиционных моделей

Традиционные (основанные на подсчете) стратегии разработки функций для текстовых данных включают модели, принадлежащие к семейству моделей, широко известному как модель «Мешок слов». Сюда входят частоты терминов, TF-IDF (частота термина с обратной частотой документа), N-граммы и т. Д. Несмотря на то, что они являются эффективными методами извлечения функций из текста, из-за неотъемлемой природы модели, представляющей собой просто мешок неструктурированных слов, мы теряем дополнительную информацию, такую ​​как семантика, структура, последовательность и контекст вокруг соседних слов в каждом текстовом документе. Это формирует достаточную мотивацию для нас исследовать более сложные модели, которые могут фиксировать эту информацию и давать нам функции, которые представляют собой векторное представление слов, широко известное как встраивание.

Необходимость встраивания слов

Хотя в этом есть некоторый смысл, почему мы должны быть достаточно мотивированы, чтобы изучать и строить эти вложения слов? Что касается систем распознавания речи или изображений, вся информация уже представлена ​​в форме богатых плотных векторов признаков, встроенных в наборы данных большой размерности, такие как спектрограммы звука и интенсивности пикселей изображения. Однако когда дело доходит до необработанных текстовых данных, особенно моделей на основе подсчета, таких как Bag of Words, мы имеем дело с отдельными словами, которые могут иметь свои собственные идентификаторы и не фиксируют семантические отношения между словами. Это приводит к огромным разреженным векторам слов для текстовых данных, и поэтому, если у нас недостаточно данных, мы можем в конечном итоге получить плохие модели или даже переобучить данные из-за проклятия размерности.

Чтобы преодолеть недостатки, связанные с потерей семантики и редкостью функций в функциях на основе моделей, нам необходимо использовать Модели векторного пространства (VSM) в таком способ, которым мы можем встраивать векторы слов в это непрерывное векторное пространство на основе семантического и контекстного сходства. Фактически, гипотеза распределения в поле семантика распределения сообщает нам, что слова, которые встречаются и используются в одном контексте, семантически похожи друг на друга и имеют схожие значения. Проще говоря, слово характеризует компания, которую оно держит. Одна из известных статей, подробно рассказывающих об этих семантических векторах слов и их различных типах, - ‘ Не считайте, прогнозируйте! Систематическое сравнение семантических векторов подсчета контекста и предсказания контекста Барони и др.». Мы не будем вдаваться в подробности, но, вкратце, есть два основных типа методов для контекстных векторов слов. Методы на основе подсчета, такие как Скрытый семантический анализ (LSA), которые можно использовать для вычисления некоторых статистических показателей. того, как часто слова встречаются с соседними с ними словами в корпусе, а затем построение плотных векторов слов для каждого слова из этих мер. Методы прогнозирования, такие как языковые модели на основе нейронной сети, пытаются предсказать слова из соседних слов, глядя на последовательности слов. в корпусе, и в процессе он изучает распределенные представления, давая нам плотные вложения слов. В этой статье мы сосредоточимся на этих методах прогнозирования.

Стратегии разработки функций

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

import pandas as pd
import numpy as np
import re
import nltk
import matplotlib.pyplot as plt
pd.options.display.max_colwidth = 200
%matplotlib inline

Теперь мы возьмем несколько корпусов документов, по которым мы проведем весь наш анализ. Для одного из корпусов мы будем повторно использовать корпус из нашей предыдущей статьи Часть 3: Традиционные методы для текстовых данных. Мы упоминаем код следующим образом для простоты понимания.

Наш игрушечный корпус состоит из документов, относящихся к нескольким категориям. Еще один корпус, который мы будем использовать в этой статье, - это Версия Библии короля Иакова, доступная бесплатно на сайте Project Gutenberg через модуль corpus в nltk. Мы скоро загрузим это в следующем разделе. Прежде чем говорить о разработке функций, нам нужно предварительно обработать и нормализовать этот текст.

Предварительная обработка текста

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

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

norm_corpus = normalize_corpus(corpus)
norm_corpus
Output
------
array(['sky blue beautiful', 'love blue beautiful sky',
       'quick brown fox jumps lazy dog',
       'kings breakfast sausages ham bacon eggs toast beans',
       'love green eggs ham sausages bacon',
       'brown fox quick blue dog lazy', 
       'sky blue sky beautiful today',
       'dog lazy brown fox quick'],
      dtype='<U51')

Давайте теперь загрузим наш другой корпус, основанный на Библии в версии короля Иакова, используя nltk и предварительно обработав текст.

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

Output
------
Total lines: 30103

Sample line: ['1', ':', '6', 'And', 'God', 'said', ',', 'Let', 'there', 'be', 'a', 'firmament', 'in', 'the', 'midst', 'of', 'the', 'waters', ',', 'and', 'let', 'it', 'divide', 'the', 'waters', 'from', 'the', 'waters', '.']

Processed line: god said let firmament midst waters let divide waters waters

Давайте посмотрим на некоторые из популярных моделей встраивания слов и инженерные функции из нашего корпуса!

Модель Word2Vec

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

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

  • Модель непрерывного мешка слов (CBOW)
  • Модель скип-грамма

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

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

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

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

Реализация модели непрерывного набора слов (CBOW)

Хотя отлично использовать надежные фреймворки, в которых есть модель Word2Vec, например gensim, давайте попробуем реализовать это с нуля, чтобы получить некоторое представление о том, как на самом деле все работает за кулисами. Мы будем использовать наш корпус Библии, содержащийся в переменной norm_bible, для обучения нашей модели. Реализация будет сосредоточена на четырех частях.

  • Расширьте словарный запас корпуса
  • Создайте генератор CBOW (контекст, цель)
  • Постройте архитектуру модели CBOW
  • Обучите модель
  • Получить вложения слов

Без промедления, приступим!

Расширьте словарный запас корпуса

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

Output
------
Vocabulary Size: 12425
Vocabulary Sample: [('perceived', 1460), ('flagon', 7287), ('gardener', 11641), ('named', 973), ('remain', 732), ('sticketh', 10622), ('abstinence', 11848), ('rufus', 8190), ('adversary', 2018), ('jehoiachin', 3189)]

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

Создайте генератор CBOW (контекст, цель)

Нам нужны пары, которые состоят из целевого центрального слова и окружающих контекстных слов. В нашей реализации целевое слово имеет длину 1, а окружающий контекст - длины 2 x window_size, где мы берем window_size слов до и после целевого слова в нашем корпусе. Это станет яснее на следующем примере.

Context (X): ['old','testament','james','bible'] -> Target (Y): king
Context (X): ['first','book','called','genesis'] -> Target(Y): moses
Context(X):['beginning','god','heaven','earth'] -> Target(Y):created
Context (X):['earth','without','void','darkness'] -> Target(Y): form
Context (X): ['without','form','darkness','upon'] -> Target(Y): void
Context (X): ['form', 'void', 'upon', 'face'] -> Target(Y): darkness
Context (X): ['void', 'darkness', 'face', 'deep'] -> Target(Y): upon
Context (X): ['spirit', 'god', 'upon', 'face'] -> Target (Y): moved
Context (X): ['god', 'moved', 'face', 'waters'] -> Target (Y): upon
Context (X): ['god', 'said', 'light', 'light'] -> Target (Y): let
Context (X): ['god', 'saw', 'good', 'god'] -> Target (Y): light

Предыдущий вывод должен дать вам некоторое представление о том, как X формирует наши контекстные слова, и мы пытаемся предсказать целевое центральное слово Y исходя из этого контекста. Например, если исходный текст был «вначале бог сотворил небо и землю», который после предварительной обработки и удаления игнорируемых слов стал «начальный бог создал небо earth ', и мы пытаемся достичь именно этого. Учитывая [начало, бог, небо, земля] в качестве контекста, каково целевое центральное слово, которое в данном случае является 'created' .

Постройте архитектуру модели CBOW

Теперь мы используем keras поверх tensorflow для построения нашей архитектуры глубокого обучения для модели CBOW. Для этого нашими входными данными будут наши контекстные слова, которые передаются на слой внедрения (инициализируются случайными весами). Вложения слов распространяются на уровень лямбда, где мы усредняем вложения слов (отсюда и название CBOW, потому что мы на самом деле не учитываем порядок или последовательность в контекстных словах при усреднении) , а затем мы передаем это усредненное встраивание контекста в плотный слой softmax, который предсказывает наше целевое слово. Мы сопоставляем это с фактическим целевым словом, вычисляем потерю, используя потерю categorical_crossentropy, и выполняем обратное распространение с каждой эпохой для обновления слоя внедрения в процессе. Следующий код показывает нам архитектуру нашей модели.

Если у вас все еще возникают трудности с визуализацией вышеупомянутой модели глубокого обучения, я бы порекомендовал вам прочитать документы, о которых я упоминал ранее. Я попытаюсь кратко изложить основные концепции этой модели. У нас есть слова контекста ввода с размерами (2 x window_size), мы передадим их на уровень внедрения размера (vocab_size x embed_size), что даст нам плотные вложения слов для каждого из этих контекстных слов (1 x embed_size for each word). Затем мы используем слой лямбда, чтобы усреднить эти вложения и получить среднюю плотность вложения (1 x embed_size) , который отправляется на плотный слой softmax, который выводит наиболее вероятное целевое слово. Мы сравниваем это с фактическим целевым словом, вычисляем потерю, распространяем ошибки в обратном направлении для корректировки весов (на уровне внедрения) и повторяем этот процесс для всех пар (контекст, цель) для нескольких эпох. Следующий рисунок пытается объяснить то же самое.

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

Обучите модель

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

Epoch: 1 	Loss: 4257900.60084
Epoch: 2 	Loss: 4256209.59646
Epoch: 3 	Loss: 4247990.90456
Epoch: 4 	Loss: 4225663.18927
Epoch: 5 	Loss: 4104501.48929

Примечание. Запуск этой модели требует больших вычислительных ресурсов и работает лучше, если обучение выполняется с использованием графического процессора. Я тренировал это на экземпляре AWS p2.x с графическим процессором Tesla K80, и мне потребовалось около 1,5 часов всего за 5 эпох!

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

Получить вложения слов

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

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

(12424, 12424)
{'egypt': ['destroy', 'none', 'whole', 'jacob', 'sea'],
 'famine': ['wickedness', 'sore', 'countries', 'cease', 'portion'],
 'god': ['therefore', 'heard', 'may', 'behold', 'heaven'],
 'gospel': ['church', 'fowls', 'churches', 'preached', 'doctrine'],
 'jesus': ['law', 'heard', 'world', 'many', 'dead'],
 'john': ['dream', 'bones', 'held', 'present', 'alive'],
 'moses': ['pharaoh', 'gate', 'jews', 'departed', 'lifted'],
 'noah': ['abram', 'plagues', 'hananiah', 'korah', 'sarah']}

Вы можете ясно видеть, что некоторые из них имеют смысл контекстно (бог, небо), (евангелие, церковь) и так далее, а некоторые могут и нет. Обучение большему количеству эпох обычно дает лучшие результаты. Теперь мы рассмотрим архитектуру skip-gram, которая часто дает лучшие результаты по сравнению с CBOW.

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

Архитектура модели Skip-gram обычно пытается добиться обратного тому, что делает модель CBOW. Он пытается предсказать исходные слова контекста (окружающие слова) по целевому слову (центральному слову). Учитывая нашу простую фразу из предыдущего, «быстрая коричневая лисица перепрыгивает через ленивую собаку». Если мы использовали модель CBOW, мы получаем пары (context_window, target_word), где, если мы рассматриваем контекстное окно размером 2, мы есть такие примеры, как ([quick, fox], brown), ([the, brown], quick), ([the, dog], lazy) и т. д. Теперь, учитывая, что цель модели skip-gram - предсказать контекст по целевому слову, модель обычно инвертирует контексты и цели и пытается предсказать каждое контекстное слово по целевому слову. Следовательно, задача заключается в том, чтобы предсказать контекст [quick, fox] по заданному целевому слову 'коричневый' или [the, brown] задано целевое слово 'quick' и так далее. Таким образом, модель пытается предсказать слова context_window на основе target_word.

Точно так же, как мы обсуждали в модели CBOW, нам нужно смоделировать эту архитектуру Skip-gram сейчас как модель классификации глубокого обучения, чтобы мы принимали целевое слово в качестве входных данных и пытались предсказать слова контекста. Это становится немного сложным, поскольку у нас есть несколько слов в нашем контексте. Мы еще больше упрощаем это, разбивая каждую пару (target, context_words) на (target, context) пары, например что каждый контекст состоит только из одного слова. Следовательно, наш предыдущий набор данных преобразуется в пары типа (коричневый, быстрый), (коричневый, лисий), (быстрый, the), (быстрый, коричневый) и т. Д. . Но как контролировать или обучать модель знать, что контекстно, а что нет?

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

Реализация модели скип-грамм

Давайте теперь попробуем реализовать эту модель с нуля, чтобы получить некоторое представление о том, как все работает за кулисами, а также чтобы мы могли сравнить ее с нашей реализацией модели CBOW. Мы будем использовать наш корпус Библии, как обычно, который содержится в переменной norm_bible, для обучения нашей модели. Реализация будет сосредоточена на пяти частях.

  • Расширьте словарный запас корпуса
  • Создайте генератор пропусков [(цель, контекст), релевантность]
  • Постройте архитектуру модели скип-грамма
  • Обучите модель
  • Получить вложения слов

Давайте приступим к созданию нашей модели Word2Vec со скип-граммом!

Расширьте словарный запас корпуса

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

Vocabulary Size: 12425
Vocabulary Sample: [('perceived', 1460), ('flagon', 7287), ('gardener', 11641), ('named', 973), ('remain', 732), ('sticketh', 10622), ('abstinence', 11848), ('rufus', 8190), ('adversary', 2018), ('jehoiachin', 3189)]

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

Создайте генератор пропуска граммов [(цель, контекст), релевантность]

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

Примечание. Функция skipgrams(…) присутствует в keras.preprocessing.sequence

Эта функция преобразует последовательность индексов слов (список целых чисел) в кортежи слов вида:

- (слово, слово в том же окне), с меткой 1 (положительные образцы).

- (слово, случайное слово из словаря) с меткой 0 (отрицательные образцы).

(james (1154), king (13)) -> 1
(king (13), james (1154)) -> 1
(james (1154), perform (1249)) -> 0
(bible (5766), dismissed (6274)) -> 0
(king (13), alter (5275)) -> 0
(james (1154), bible (5766)) -> 1
(king (13), bible (5766)) -> 1
(bible (5766), king (13)) -> 1
(king (13), compassion (1279)) -> 0
(james (1154), foreskins (4844)) -> 0

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

Постройте архитектуру модели skip-gram

Теперь мы используем keras поверх tensorflow, чтобы построить нашу архитектуру глубокого обучения для модели skip-gram. Для этого нашими входными данными будут наше целевое слово и контекст или случайная пара слов. Каждый из них передается на собственный уровень внедрения (инициализируется случайными весами). Как только мы получаем вложения слова для цели и контекстного слова, мы передаем его на уровень слияния, где вычисляем скалярное произведение этих двух векторов. Затем мы передаем это значение скалярного произведения плотному сигмовидному слою, который предсказывает либо 1, либо 0 в зависимости от того, является ли пара слов контекстно релевантной или просто случайными словами (Y ' ). Мы сопоставляем это с фактической меткой релевантности (Y), вычисляем потери, используя потери mean_squared_error, и выполняем обратное распространение с каждой эпохой для обновления слоя внедрения в процессе. Следующий код показывает нам архитектуру нашей модели.

Понять описанную выше модель глубокого обучения довольно просто. Тем не менее, я попытаюсь кратко изложить основные концепции этой модели простыми словами для облегчения понимания. У нас есть пара входных слов для каждого обучающего примера, состоящая из одного входного целевого слова с уникальным числовым идентификатором и одного контекстного слова с уникальным числовым идентификатором. Если это положительный образец, слово имеет контекстное значение, является контекстным словом и нашим label Y = 1, иначе, если это отрицательный образец, слово не имеет контекстного значения, просто случайное слово и наш ярлык Y = 0. Мы передадим каждый из них на собственный слой внедрения, имеющий размер (vocab_size x embed_size), что даст нам плотное встраивание слов для каждого из этих двух слов (1 x embed_size for each word). Затем мы используем слой слияния для вычисления скалярного произведения этих двух внедрений и получения значения скалярного произведения. . Затем он отправляется на плотный сигмовидный слой, который выводит либо 1, либо 0. Мы сравниваем это с фактической меткой Y (1 или 0), вычисляем потери, выполняем обратное распространение. ошибки, чтобы скорректировать веса (в слое внедрения) и повторить этот процесс для всех пар (цель, контекст) для нескольких эпох. Следующий рисунок пытается объяснить то же самое.

Теперь приступим к обучению нашей модели с помощью наших скип-грамм.

Обучите модель

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

Epoch: 1 Loss: 4529.63803683
Epoch: 2 Loss: 3750.71884749
Epoch: 3 Loss: 3752.47489296
Epoch: 4 Loss: 3793.9177565
Epoch: 5 Loss: 3716.07605051

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

Получить вложения слов

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

Таким образом, вы можете ясно видеть, что каждое слово имеет плотное вложение размером (1x100), как показано в предыдущем выводе, аналогично тому, что мы получили из модели CBOW. Давайте теперь применим метрику евклидова расстояния к этим векторам плотного вложения, чтобы сгенерировать метрику попарного расстояния для каждого слова в нашем словаре. Затем мы можем найти n-ближайших соседей каждого интересующего слова на основе кратчайшего (евклидова) расстояния, аналогично тому, что мы сделали для встраиваний из нашей модели CBOW.

(12424, 12424)
{'egypt': ['pharaoh', 'mighty', 'houses', 'kept', 'possess'],
 'famine': ['rivers', 'foot', 'pestilence', 'wash', 'sabbaths'],
 'god': ['evil', 'iniquity', 'none', 'mighty', 'mercy'],
 'gospel': ['grace', 'shame', 'believed', 'verily', 'everlasting'],
 'jesus': ['christ', 'faith', 'disciples', 'dead', 'say'],
 'john': ['ghost', 'knew', 'peter', 'alone', 'master'],
 'moses': ['commanded', 'offerings', 'kept', 'presence', 'lamb'],
 'noah': ['flood', 'shem', 'peleg', 'abram', 'chose']}

Вы можете ясно видеть из результатов, что многие похожие слова для каждого из интересующих слов имеют смысл, и мы получили лучшие результаты по сравнению с нашей моделью CBOW. Давайте теперь визуализируем вложения этих слов, используя t-SNE, что означает t-распределенное стохастическое встраивание соседей, популярное уменьшение размерности. техника для визуализации пространств более высоких измерений в более низких измерениях (например, 2-D).

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

Надежные модели Word2Vec с Gensim

Хотя наши реализации достаточно приличны, они недостаточно оптимизированы, чтобы хорошо работать на больших корпусах. Платформа gensim, созданная Радимом Жегуржеком, представляет собой надежную, эффективную и масштабируемую реализацию модели Word2Vec. Мы будем использовать то же самое в нашем корпусе Библии. В нашем рабочем процессе мы будем токенизировать наш нормализованный корпус, а затем сосредоточимся на следующих четырех параметрах в модели Word2Vec, чтобы построить его.

  • size: слово "размерность встраивания"
  • window: размер контекстного окна.
  • min_count: минимальное количество слов.
  • sample: настройка субдискретизации для часто встречающихся слов.

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

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

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

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

Применение функций Word2Vec для задач машинного обучения

Если вы помните, как читали предыдущую статью Часть 3: Традиционные методы для текстовых данных, возможно, вы видели, как я использовал функции для некоторых реальных задач машинного обучения, таких как кластеризация. Давайте воспользуемся другим нашим главным корпусом и попробуем добиться того же. Для начала мы построим простую модель Word2Vec на корпусе и визуализируем вложения.

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

w2v_model.wv['sky']
Output
------
array([ 0.04576328,  0.02328374, -0.04483001,  0.0086611 ,  0.05173225, 0.00953358, -0.04087641, -0.00427487, -0.0456274 ,  0.02155695], dtype=float32)

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

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

Мы видим, что наш алгоритм сгруппировал каждый документ в нужную группу на основе наших функций Word2Vec. Довольно аккуратно! Мы также можем визуализировать, как каждый документ расположен в каждом кластере, используя Анализ основных компонентов (PCA), чтобы уменьшить размеры элемента до 2-D, а затем визуализировать то же самое. (цветовой кодировкой каждого кластера).

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

МОДЕЛЬ ПЕРЧАТКИ

Модель GloVe расшифровывается как Global Vectors, которая представляет собой модель обучения без учителя, которую можно использовать для получения плотных векторов слов, подобных Word2Vec. Однако методика отличается, и обучение выполняется на агрегированной глобальной матрице совпадения слов и слов, что дает нам векторное пространство со значимыми подструктурами. Этот метод был изобретен в Стэнфорде Pennington et al. и я рекомендую вам прочитать оригинальную статью о GloVe « GloVe: глобальные векторы для представления слов Пеннингтона и др.» это отличное чтение, чтобы получить представление о том, как работает эта модель.

Мы не будем здесь подробно описывать реализацию модели с нуля, но если вас интересует реальный код, вы можете проверить официальную страницу GloVe. Мы будем упрощать здесь задачу и попытаемся понять основные концепции, лежащие в основе модели GloVe. Мы говорили о методах матричной факторизации на основе подсчета, таких как LSA, и методах прогнозирования, таких как Word2Vec. В документе утверждается, что в настоящее время обе семьи страдают существенными недостатками. Такие методы, как LSA, эффективно используют статистическую информацию, но они относительно плохо справляются с задачей сопоставления слов, например, как мы обнаружили семантически похожие слова. Такие методы, как skip-gram, могут лучше справиться с задачей аналогии, но они плохо используют статистику корпуса на глобальном уровне.

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

Принимая во внимание матрицу Word-Context (WC), матрицу Word-Feature (WF) и Feature-Context (FC), мы пытаемся разложить WC = WF x FC на множители, так что мы стремимся восстановить WC из WF и FC путем их умножения. Для этого мы обычно инициализируем WF и FC с некоторыми случайными весами и пытаемся умножить их, чтобы получить WC ' (приблизительное значение WC) и измерьте, насколько оно близко к WC. Мы делаем это несколько раз, используя Стохастический градиентный спуск (SGD), чтобы минимизировать ошибку. Наконец, матрица функций слова (WF) дает нам встраивание слов для каждого слова, в котором F может быть предустановлено на определенное количество размеров. Очень важно помнить, что модели Word2Vec и GloVe очень похожи по принципу работы. Оба они стремятся построить векторное пространство, в котором на положение каждого слова влияют его соседние слова в зависимости от их контекста и семантики. Word2Vec начинается с локальных индивидуальных примеров пар совпадения слов, а GloVe - с глобальной агрегированной статистики совместной встречаемости по всем словам в корпусе.

Применение функций GloVe для задач машинного обучения

Давайте попробуем использовать вложения на основе GloVe для нашей задачи кластеризации документов. Очень популярный фреймворк spacy позволяет использовать встраивание GloVe на основе различных языковых моделей. Вы также можете получить предварительно обученные векторы слов и загрузить их по мере необходимости с помощью gensim или spacy. Сначала мы установим spacy и воспользуемся моделью en_vectors_web_lg, которая состоит из 300-мерных векторов слов, обученных на Common Crawl с GloVe.

# Use the following command to install spaCy
> pip install -U spacy
OR
> conda install -c conda-forge spacy
# Download the following language model and store it in disk
https://github.com/explosion/spacy-models/releases/tag/en_vectors_web_lg-2.0.0
# Link the same to spacy 
> python -m spacy link ./spacymodels/en_vectors_web_lg-2.0.0/en_vectors_web_lg en_vecs
Linking successful
    ./spacymodels/en_vectors_web_lg-2.0.0/en_vectors_web_lg --> ./Anaconda3/lib/site-packages/spacy/data/en_vecs
You can now load the model via spacy.load('en_vecs')

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

Total word vectors: 1070971

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

Теперь мы можем использовать t-SNE, чтобы визуализировать эти вложения, аналогично тому, что мы делали, используя наши вложения Word2Vec.

Прелесть spacy в том, что он автоматически предоставит вам усредненные вложения для слов в каждом документе без необходимости реализации функции, как мы сделали в Word2Vec. Мы будем использовать то же самое, чтобы получить функции документа для нашего корпуса, и использовать кластеризацию k-means для кластеризации наших документов.

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

Вышеупомянутые эксперименты были выполнены путем обучения 300-мерных векторов на одном и том же корпусе токенов 6B (Wikipedia 2014 + Gigaword 5) с тем же словарем на 400000 слов и симметричным контекстным окном размером 10 на случай, если кому-то интересны детали.

Модель FastText

Модель FastText была впервые представлена ​​Facebook в 2016 году как расширение и предположительно улучшение стандартной модели Word2Vec. На основе оригинальной статьи Миколова и др. « Обогащение векторов слов информацией о подсловах ». это отличное чтение, чтобы получить более полное представление о том, как работает эта модель. В целом FastText - это среда для изучения представлений слов, а также выполнения надежной, быстрой и точной классификации текста. Фреймворк находится в открытом доступе на Facebook на GitHub и утверждает, что имеет следующее.

Хотя я не реализовал эту модель с нуля, основываясь на исследовательской работе, ниже я узнал о том, как эта модель работает. Как правило, модели прогнозирования, такие как модель Word2Vec, обычно рассматривают каждое слово как отдельную сущность (например, where) и создают для слова плотное встраивание. Однако это представляет собой серьезное ограничение для языков с обширным словарным запасом и множеством редких слов, которые могут не часто встречаться в разных корпусах. Модель Word2Vec обычно игнорирует морфологическую структуру каждого слова и рассматривает слово как единое целое. Модель FastText рассматривает каждое слово как набор n-граммов символов. В статье это также называется моделью подслова.

Мы добавляем специальные граничные символы и в начало и конец слов. Это позволяет нам отличать префиксы и суффиксы от других последовательностей символов. Мы также включаем само слово w в набор его n-граммов, чтобы узнать представление каждого слова (в дополнение к его символьным n-граммам). Если взять в качестве примера слово где и n = 3 (триграммы), оно будет представлено как символы n-граммы: ‹wh, whe, her, ere, re› и специальная последовательность ‹where› представляет собой все слово. Обратите внимание, что последовательность, соответствующая слову ‹her›, отличается от трехграммы her из слово где.

На практике в документе рекомендуется извлекать все n-граммы для n ≥ 3 и n ≤ 6. Это очень простой подход, и можно рассмотреть различные наборы n-граммов, например, принимая все префиксы и суффиксы. Обычно мы связываем векторное представление (вложение) с каждой n-граммой слова. Таким образом, мы можем представить слово суммой векторных представлений его n-граммов или средним значением вложений этих n-граммов. Таким образом, из-за этого эффекта использования n-граммов отдельных слов на основе их символов, существует более высокий шанс для редких слов получить хорошее представление, поскольку их n-граммы на основе символов должны встречаться в других словах корпуса.

Применение функций FastText для задач машинного обучения

Пакет gensim имеет хорошие оболочки, предоставляющие нам интерфейсы для использования модели FastText, доступной в модуле gensim.models.fasttext. Давайте еще раз применим это к нашему корпусу Библии и посмотрим на наши слова, представляющие интерес, и наиболее похожие слова.

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

Примечание. Выполнение этой модели требует больших вычислительных ресурсов и обычно занимает больше времени по сравнению с моделью пропуска граммов, поскольку она учитывает n-граммы для каждого слова. Это работает лучше, если тренировать с использованием графического процессора или хорошего процессора. Я обучил это на экземпляре AWS p2.x, и это заняло у меня около 10 минут по сравнению с более чем 2–3 часами в обычной системе.

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

Мы видим много интересных закономерностей! Ной, его сын Шем и дед Мафусаил близки друг другу. Мы также видим Бога, связанного с Моисеем и Египтом, где он перенес библейские казни, включая голод и мор. . Также Иисус и некоторые из его учеников тесно связаны друг с другом.

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

ft_model.wv['jesus']
array([-0.23493268,  0.14237943,  0.35635167,  0.34680951,    
        0.09342121,..., -0.15021783, -0.08518736, -0.28278247,   
       -0.19060139], dtype=float32)

Имея эти вложения, мы можем выполнять некоторые интересные задачи на естественном языке. Один из них - найти сходство между разными словами (сущностями).

print(ft_model.wv.similarity(w1='god', w2='satan'))
print(ft_model.wv.similarity(w1='god', w2='jesus'))
Output
------
0.333260876685
0.698824900473

Мы видим, что "бог" более тесно связан с "иисусом", а не 'сатана' на основе текста из нашего корпуса Библии. Вполне актуально!

Учитывая наличие вложения слов, мы можем даже найти нечетные слова из набора слов следующим образом.

st1 = "god jesus satan john"
print('Odd one out for [',st1, ']:',  
      ft_model.wv.doesnt_match(st1.split()))
st2 = "john peter james judas"
print('Odd one out for [',st2, ']:', 
      ft_model.wv.doesnt_match(st2.split()))
Output
------
Odd one out for [ god jesus satan john ]: satan
Odd one out for [ john peter james judas ]: judas

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

Заключение

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

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

Чтобы узнать о стратегиях разработки функций для дискретных категориальных данных, ознакомьтесь с частью 2 этой серии!

Чтобы узнать о традиционных стратегиях разработки функций для неструктурированных текстовых данных, ознакомьтесь с частью 3 этой серии!

Весь код и наборы данных, используемые в этой статье, доступны на моем GitHub

Код также доступен как Блокнот Jupyter.

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

Если у вас есть какие-либо отзывы, комментарии или интересные идеи, которыми можно поделиться о моей статье или науке о данных в целом, не стесняйтесь обращаться ко мне на моем канале в социальных сетях LinkedIn.