Вы подписаны на Машинное обучение доступно
Отлично! завершите оплату для полного доступа к Машинное обучение доступно
Снова приветствуем Вас! Вы успешно авторизовались
Успех! Аккаунт активирован, и Вы имеете полный доступ к контенту.
Скип-грамм (Skip Gram)

Скип-грамм (Skip Gram)

in

Скип-грамм - это один из методов обучения без учителя, который используется для поиска близких по тематике слов для заданного слова. Алгоритм противоположен CBOW: здесь целевое слово вводится, а слова контекста выводятся.

Скип-грамм– это одна из моделей word2vec, и слова представлены в них как вектор в n-мерном пространстве (или n-мерном пространстве признаков), приближая похожие слова друг к другу.

Модель скип-граммы - одна из самых важных концепций в Обработке естественного языка (NLP), и мы должны понимать, как именно она работает.

Во-первых, нам нужно осознать, что компьютеры не понимают слов. Все, что понимает компьютер, – это числа. Поэтому нам нужно найти способ преобразовать каждое данное слово в число. Есть два способа сделать это – быстрое кодирование (One-Hot Encoding) и вектора вещественных чисел (Continuous Vectors).

Быстрое кодирование

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

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

{'в', 'даже', 'душ', 'и', 'испачкать', 'под', 'с', 'скорей', 'смыть', 'становиться', 'тушь', 'ты', 'уши', 'шея', 'черный', 'шея'}

Для слова 'даже' быстрое кодирование выглядит так:

[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

А для "черный" – так:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]

Однако метод обладает рядом недостатков:

  • Длина словаря может доходить до 1 миллиона элементов, что делает хранении данных крайне неэффективным
  • Такая кодировка не передает смысл слова: расстояние между кодировками любых двух слов всегда одинаково. Нам нужно кодирование, дающее представление о смысле слова. Здесь в игру вступают вещественные векторы.

Вещественные векторы

Такие векторы состоят из действительных чисел (а не только 0 или 1). В этом представлении нет фиксированного правила для длины таких векторов. Вы можете выбрать любую длину (любое количество функций) для представления слов, присутствующих в данном словаре.
Пример. Возьмем слова "Бэтмен", "Джокер", "Человек-паук" и "Танос". Вектора каждого из этих слов для трех характеристик супергероев выглядят следующим образом:

word2vec(‘Бэтмен’) = [0.9, 0.8, 0.2]
word2vec(‘Джокер’) = [0.8, 0.3, 0.1]
word2vec(‘Человек-паук’) = [0.2, .9, 0.8]
word2vec(‘Танос’) = [0.3, 0.1, 0.9]

Первый элемент этих векторов олицетворяет принадлежность к Вселенной DC. Обратите внимание: «Бэтмен» и «Джокер» имеют более высокие значения для своей 1-й функции, потому что принадлежат ко Вселенной DC.

Второй элемент в представлении word2vec здесь отвечает за "доброту" персонажа. Вот почему «Бэтмен» и «Человек-паук» имеют более высокие значения, а «Джокер» и «Танос» – меньшие.

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

Происхождение словесных вложений и вещественных векторов

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

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

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

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

Модель скип-граммов, как и все другие модели word2vec, использует прием, который также используется во многих других алгоритмах Машинного обучения (ML). Поскольку у нас нет предварительно подготовленных ярлыков, связанных со словами, это Обучение с частичным привлечением учителя (Semi-Supervised Learning), потому что у нас нет прямых ярлыков, связанных со словами, но мы используем соседние слова (контекстного слова в предложении) в качестве ярлыков.

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

На изображении выше показано, как создаются пары слов "контекст – цель", которые можно использовать для обучения модели скип-граммов. Мы используем параметр "размер окна" (в данном случае он равен двум), который учитывает одно слово слева и два справа от контекстного. Давайте изучим процесс подробнее.

  1. У нас есть предложение. Берем первое слово "русский": это наше контекстное слово. Мы составляем пары из этого контекстного слова со словами справа ("медленно" и "запрягает"). Таким образом, у нас есть 2 пары. Первая пара – "русский", "медленно", а вторая – "русский", "запрягает". Мы не можем соединить контекстное слово "русский" со словами слева, потому что слов там нет.
  2. Теперь мы переходим ко второму контекстному слову ("медленно") и соединяем его со словом слева и двумя справа. На этот раз мы получим три пары: "медленно", "русский"; "медленно", "запрягает"; "медленно", "да".
  3. Мы продолжаем создавать пары контекстно-целевых слов для всех возможных элементов датасета. По сути, мы здесь собираем пары слов, которые можно найти рядом друг с другом. Мы фиксируем контекст и собираемся использовать эту контекстную информацию в дальнейшем. Надеюсь, теперь понятно, почему этот алгоритм называется обучением с частичным привлечением учителя.

Обучение

На данный момент у нас есть готовый словарь из 10 000 слов, а также пары слов "контекст – цель". Мы берем вектор быстрого кодирования контекстного слова и передаем его в нейронную сеть. Эти входные данные умножаются на веса (Weights) скрытых слоев, и в конце мы получаем выходной вектор 10 000 компонентов.

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

Затем кросс-энтропия (Cross-Entropy) применяется для вычисления потерь и обновляет веса.

Применение

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

from keras.preprocessing.sequence import skipgrams

# Генерация скип-граммов с размером окна 10
skip_grams = [skipgrams(wid, vocabulary_size = vocab_size, window_size = 10) for wid in wids]

# Отображение семплов скип-грамма
pairs, labels = skip_grams[0][0], skip_grams[0][1]
for i in range(10):
    print("({:s} ({:d}), {:s} ({:d})) -> {:d}".format(
          id2word[pairs[i][0]], pairs[i][0], 
          id2word[pairs[i][1]], pairs[i][1], 
          labels[i]))

Мы можем увидеть, что релевантно друг другу, а что нет, на основе метки (0 или 1).

(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