Word2Vec

Посмотреть на TensorFlow.org Запустить в Google Colab Посмотреть исходный код на GitHubСкачать блокнот

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

В этих статьях предлагалось два метода изучения представлений слов:

  • Модель непрерывного набора слов, которая предсказывает среднее слово на основе окружающих контекстных слов. Контекст состоит из нескольких слов до и после текущего (среднего) слова. Эта архитектура называется моделью набора слов, поскольку порядок слов в контексте не важен.
  • Модель непрерывной скип-граммы, которая предсказывает слова в определенном диапазоне до и после текущего слова в том же предложении. Рабочий пример этого приведен ниже.

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

Скип-грамм и отрицательная выборка

В то время как модель набора слов предсказывает слово с учетом соседнего контекста, модель пропуска грамматики предсказывает контекст (или соседей) слова с учетом самого слова. Модель обучается на скип-граммах, которые представляют собой n-граммы, которые позволяют пропускать токены (см. Пример на диаграмме ниже). Контекст слова может быть представлен через набор пар пропуска грамматики (target_word, context_word) где context_word появляется в соседнем контексте target_word .

Рассмотрим следующее предложение из 8 слов.

Широкая дорога сияла на палящем солнце.

Контекстные слова для каждого из 8 слов этого предложения определяются размером окна. Размер окна определяет диапазон слов по обе стороны от target_word которые можно рассматривать как context word . Взгляните на эту таблицу скип-грамм для целевых слов, основанных на разных размерах окна.

word2vec_skipgrams

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

word2vec_skipgram_objective

где c - размер обучающего контекста. Базовая формулировка скип-граммы определяет эту вероятность с помощью функции softmax.

word2vec_full_softmax

где v и v ' - целевые и контекстные векторные представления слов, а W - размер словаря.

Вычисление знаменателя этой формулировки включает в себя выполнение полного softmax по всем словарным словам, которые часто являются большими (10 5 -10 7 ) терминами.

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

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

Отрицательный образец определяется как пара (target_word, context_word), так что context_word не появляется в окрестности window_size для target_word. Для примера предложения это несколько потенциальных отрицательных выборок (когда window_size равно 2).

(hot, shimmered)
(wide, hot)
(wide, sun)

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

Настраивать

import io
import re
import string
import tensorflow as tf
import tqdm

from tensorflow.keras import Model
from tensorflow.keras.layers import Dot, Embedding, Flatten
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
# Load the TensorBoard notebook extension
%load_ext tensorboard
SEED = 42
AUTOTUNE = tf.data.AUTOTUNE

Векторизовать пример предложения

Рассмотрим следующее предложение:
The wide road shimmered in the hot sun.

Обозначьте предложение:

sentence = "The wide road shimmered in the hot sun"
tokens = list(sentence.lower().split())
print(len(tokens))
8

Создайте словарь для сохранения сопоставлений токенов с целочисленными индексами.

vocab, index = {}, 1  # start indexing from 1
vocab['<pad>'] = 0  # add a padding token
for token in tokens:
  if token not in vocab:
    vocab[token] = index
    index += 1
vocab_size = len(vocab)
print(vocab)
{'<pad>': 0, 'the': 1, 'wide': 2, 'road': 3, 'shimmered': 4, 'in': 5, 'hot': 6, 'sun': 7}

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

inverse_vocab = {index: token for token, index in vocab.items()}
print(inverse_vocab)
{0: '<pad>', 1: 'the', 2: 'wide', 3: 'road', 4: 'shimmered', 5: 'in', 6: 'hot', 7: 'sun'}

Векторизуйте свое предложение.

example_sequence = [vocab[word] for word in tokens]
print(example_sequence)
[1, 2, 3, 4, 5, 1, 6, 7]

Создавайте скип-граммы из одного предложения

Модуль tf.keras.preprocessing.sequence предоставляет полезные функции, упрощающие подготовку данных для Word2Vec. Вы можете использовать tf.keras.preprocessing.sequence.skipgrams для создания пар пропуска граммов из example_sequence с заданным window_size из токенов в диапазоне [0, vocab_size) .

window_size = 2
positive_skip_grams, _ = tf.keras.preprocessing.sequence.skipgrams(
      example_sequence,
      vocabulary_size=vocab_size,
      window_size=window_size,
      negative_samples=0)
print(len(positive_skip_grams))
26

Взгляните на несколько положительных скип-грамм.

for target, context in positive_skip_grams[:5]:
  print(f"({target}, {context}): ({inverse_vocab[target]}, {inverse_vocab[context]})")
(1, 4): (the, shimmered)
(4, 3): (shimmered, road)
(4, 5): (shimmered, in)
(3, 2): (road, wide)
(1, 7): (the, sun)

Отрицательная выборка на один скип-грамм

Функция skipgrams возвращает все положительные пары skip-gram путем скольжения по заданному промежутку окна. Чтобы получить дополнительные пары скип-грамм, которые будут служить отрицательными образцами для обучения, вам нужно выбрать случайные слова из словаря. Используйте функцию tf.random.log_uniform_candidate_sampler для выборки числа отрицательных выборок num_ns для заданного целевого слова в окне. Вы можете вызвать функцию для одного целевого слова пропуска граммов и передать контекстное слово как истинный класс, чтобы исключить его из выборки.

# Get target and context words for one positive skip-gram.
target_word, context_word = positive_skip_grams[0]

# Set the number of negative samples per positive context.
num_ns = 4

context_class = tf.reshape(tf.constant(context_word, dtype="int64"), (1, 1))
negative_sampling_candidates, _, _ = tf.random.log_uniform_candidate_sampler(
    true_classes=context_class,  # class that should be sampled as 'positive'
    num_true=1,  # each positive skip-gram has 1 positive context class
    num_sampled=num_ns,  # number of negative context words to sample
    unique=True,  # all the negative samples should be unique
    range_max=vocab_size,  # pick index of the samples from [0, vocab_size]
    seed=SEED,  # seed for reproducibility
    name="negative_sampling"  # name of this operation
)
print(negative_sampling_candidates)
print([inverse_vocab[index.numpy()] for index in negative_sampling_candidates])
tf.Tensor([2 1 4 3], shape=(4,), dtype=int64)
['wide', 'the', 'shimmered', 'road']

Создайте один обучающий пример

Для данной положительной (target_word, context_word) skip-граммы теперь у вас также есть num_ns отрицательных выбранных контекстных слов, которые не появляются в окрестности размера окна target_word . Пакетный в 1 положительных context_word и num_ns отрицательные контекстные слова в один тензор. Это дает набор положительных скип-грамм (помеченных как 1 ) и отрицательных выборок (помеченных как 0 ) для каждого целевого слова.

# Add a dimension so you can use concatenation (on the next step).
negative_sampling_candidates = tf.expand_dims(negative_sampling_candidates, 1)

# Concat positive context word with negative sampled words.
context = tf.concat([context_class, negative_sampling_candidates], 0)

# Label first context word as 1 (positive) followed by num_ns 0s (negative).
label = tf.constant([1] + [0]*num_ns, dtype="int64")

# Reshape target to shape (1,) and context and label to (num_ns+1,).
target = tf.squeeze(target_word)
context = tf.squeeze(context)
label = tf.squeeze(label)

Взгляните на контекст и соответствующие метки для целевого слова из приведенного выше примера пропуска граммы.

print(f"target_index    : {target}")
print(f"target_word     : {inverse_vocab[target_word]}")
print(f"context_indices : {context}")
print(f"context_words   : {[inverse_vocab[c.numpy()] for c in context]}")
print(f"label           : {label}")
target_index    : 1
target_word     : the
context_indices : [4 2 1 4 3]
context_words   : ['shimmered', 'wide', 'the', 'shimmered', 'road']
label           : [1 0 0 0 0]

Кортеж тензоров (target, context, label) составляет один обучающий пример для обучения вашей модели Word2Vec с отрицательной выборкой с пропуском грамматики. Обратите внимание, что цель имеет форму (1,) то время как контекст и метка имеют форму (1+num_ns,)

print("target  :", target)
print("context :", context)
print("label   :", label)
target  : tf.Tensor(1, shape=(), dtype=int32)
context : tf.Tensor([4 2 1 4 3], shape=(5,), dtype=int64)
label   : tf.Tensor([1 0 0 0 0], shape=(5,), dtype=int64)

Резюме

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

word2vec_negative_sampling

Скомпилируйте все шаги в одну функцию

Таблица отбора проб на скип-грамм

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

Функция tf.keras.preprocessing.sequence.skipgrams принимает аргумент таблицы выборки для кодирования вероятностей выборки любого токена. Вы можете использовать tf.keras.preprocessing.sequence.make_sampling_table чтобы сгенерировать таблицу вероятностной выборки на основе частотного ранга и передать ее функции skipgrams . Взгляните на вероятности выборки для параметра vocab_size 10.

sampling_table = tf.keras.preprocessing.sequence.make_sampling_table(size=10)
print(sampling_table)
[0.00315225 0.00315225 0.00547597 0.00741556 0.00912817 0.01068435
 0.01212381 0.01347162 0.01474487 0.0159558 ]

sampling_table[i] обозначает вероятность выборки i-го наиболее распространенного слова в наборе данных. Функция предполагает распределение частот слов по Ципфу для выборки.

Сгенерируйте данные для обучения

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

# Generates skip-gram pairs with negative sampling for a list of sequences
# (int-encoded sentences) based on window size, number of negative samples
# and vocabulary size.
def generate_training_data(sequences, window_size, num_ns, vocab_size, seed):
  # Elements of each training example are appended to these lists.
  targets, contexts, labels = [], [], []

  # Build the sampling table for vocab_size tokens.
  sampling_table = tf.keras.preprocessing.sequence.make_sampling_table(vocab_size)

  # Iterate over all sequences (sentences) in dataset.
  for sequence in tqdm.tqdm(sequences):

    # Generate positive skip-gram pairs for a sequence (sentence).
    positive_skip_grams, _ = tf.keras.preprocessing.sequence.skipgrams(
          sequence,
          vocabulary_size=vocab_size,
          sampling_table=sampling_table,
          window_size=window_size,
          negative_samples=0)

    # Iterate over each positive skip-gram pair to produce training examples
    # with positive context word and negative samples.
    for target_word, context_word in positive_skip_grams:
      context_class = tf.expand_dims(
          tf.constant([context_word], dtype="int64"), 1)
      negative_sampling_candidates, _, _ = tf.random.log_uniform_candidate_sampler(
          true_classes=context_class,
          num_true=1,
          num_sampled=num_ns,
          unique=True,
          range_max=vocab_size,
          seed=SEED,
          name="negative_sampling")

      # Build context and label vectors (for one target word)
      negative_sampling_candidates = tf.expand_dims(
          negative_sampling_candidates, 1)

      context = tf.concat([context_class, negative_sampling_candidates], 0)
      label = tf.constant([1] + [0]*num_ns, dtype="int64")

      # Append each element from the training example to global lists.
      targets.append(target_word)
      contexts.append(context)
      labels.append(label)

  return targets, contexts, labels

Подготовить обучающие данные для Word2Vec

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

Скачать текстовый корпус

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

path_to_file = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt
1122304/1115394 [==============================] - 0s 0us/step

Прочтите текст из файла и посмотрите на первые несколько строк.

with open(path_to_file) as f: 
  lines = f.read().splitlines()
for line in lines[:20]:
  print(line)
First Citizen:
Before we proceed any further, hear me speak.

All:
Speak, speak.

First Citizen:
You are all resolved rather to die than to famish?

All:
Resolved. resolved.

First Citizen:
First, you know Caius Marcius is chief enemy to the people.

All:
We know't, we know't.

First Citizen:
Let us kill him, and we'll have corn at our own price.

Используйте непустые строки для tf.data.TextLineDataset объекта tf.data.TextLineDataset для следующих шагов.

text_ds = tf.data.TextLineDataset(path_to_file).filter(lambda x: tf.cast(tf.strings.length(x), bool))

Векторизовать предложения из корпуса

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

# Now, create a custom standardization function to lowercase the text and
# remove punctuation.
def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  return tf.strings.regex_replace(lowercase,
                                  '[%s]' % re.escape(string.punctuation), '')


# Define the vocabulary size and number of words in a sequence.
vocab_size = 4096
sequence_length = 10

# Use the text vectorization layer to normalize, split, and map strings to
# integers. Set output_sequence_length length to pad all samples to same length.
vectorize_layer = TextVectorization(
    standardize=custom_standardization,
    max_tokens=vocab_size,
    output_mode='int',
    output_sequence_length=sequence_length)

Для создания словаря вызовите adapt текстового набора данных.

vectorize_layer.adapt(text_ds.batch(1024))

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

# Save the created vocabulary for reference.
inverse_vocab = vectorize_layer.get_vocabulary()
print(inverse_vocab[:20])
['', '[UNK]', 'the', 'and', 'to', 'i', 'of', 'you', 'my', 'a', 'that', 'in', 'is', 'not', 'for', 'with', 'me', 'it', 'be', 'your']

Vectorize_layer теперь можно использовать для генерации векторов для каждого элемента в text_ds .

# Vectorize the data in text_ds.
text_vector_ds = text_ds.batch(1024).prefetch(AUTOTUNE).map(vectorize_layer).unbatch()

Получить последовательности из набора данных

Теперь у вас естьtf.data.Dataset целочисленных предложений. Чтобы подготовить набор данных для обучения модели Word2Vec, сведите набор данных в список последовательностей векторов предложений. Этот шаг необходим, поскольку вы будете перебирать каждое предложение в наборе данных для получения положительных и отрицательных примеров.

sequences = list(text_vector_ds.as_numpy_iterator())
print(len(sequences))
32777

Взгляните на несколько примеров из sequences .

for seq in sequences[:5]:
  print(f"{seq} => {[inverse_vocab[i] for i in seq]}")
[ 89 270   0   0   0   0   0   0   0   0] => ['first', 'citizen', '', '', '', '', '', '', '', '']
[138  36 982 144 673 125  16 106   0   0] => ['before', 'we', 'proceed', 'any', 'further', 'hear', 'me', 'speak', '', '']
[34  0  0  0  0  0  0  0  0  0] => ['all', '', '', '', '', '', '', '', '', '']
[106 106   0   0   0   0   0   0   0   0] => ['speak', 'speak', '', '', '', '', '', '', '', '']
[ 89 270   0   0   0   0   0   0   0   0] => ['first', 'citizen', '', '', '', '', '', '', '', '']

Создавайте обучающие примеры из последовательностей

sequences теперь является список предложений в кодировке int. Просто вызовите функцию generate_training_data() определенную ранее, чтобы сгенерировать обучающие примеры для модели Word2Vec. Напомним, функция выполняет итерацию по каждому слову из каждой последовательности, чтобы собрать положительные и отрицательные контекстные слова. Длина цели, контексты и метки должны быть одинаковыми, что соответствует общему количеству обучающих примеров.

targets, contexts, labels = generate_training_data(
    sequences=sequences,
    window_size=2,
    num_ns=4,
    vocab_size=vocab_size,
    seed=SEED)
print(len(targets), len(contexts), len(labels))
100%|██████████| 32777/32777 [00:25<00:00, 1267.26it/s]
64720 64720 64720

Настройте набор данных для повышения производительности

Чтобы выполнить эффективную пакетную обработку потенциально большого количества обучающих примеров, используйтеtf.data.Dataset API. После этого шага у вас будет объектtf.data.Dataset из элементов (target_word, context_word), (label) для обучения вашей модели Word2Vec!

BATCH_SIZE = 1024
BUFFER_SIZE = 10000
dataset = tf.data.Dataset.from_tensor_slices(((targets, contexts), labels))
dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE, drop_remainder=True)
print(dataset)
<BatchDataset shapes: (((1024,), (1024, 5, 1)), (1024, 5)), types: ((tf.int32, tf.int64), tf.int64)>

Добавьте cache() и prefetch() для повышения производительности.

dataset = dataset.cache().prefetch(buffer_size=AUTOTUNE)
print(dataset)
<PrefetchDataset shapes: (((1024,), (1024, 5, 1)), (1024, 5)), types: ((tf.int32, tf.int64), tf.int64)>

Модель и обучение

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

Подкласс модели Word2Vec

Используйте API подклассов Keras, чтобы определить модель Word2Vec со следующими слоями:

  • target_embedding : слой tf.keras.layers.Embedding который ищет встраивание слова, когда оно появляется как целевое слово. Количество параметров в этом слое: (vocab_size * embedding_dim) .
  • context_embedding : еще tf.keras.layers.Embedding слой tf.keras.layers.Embedding который ищет встраивание слова, когда оно появляется как контекстное слово. Количество параметров в этом слое такое же, как и в target_embedding , то есть (vocab_size * embedding_dim) .
  • dots : слой tf.keras.layers.Dot который вычисляет скалярное произведение целевых и контекстных встраиваний из обучающей пары.
  • flatten : а tf.keras.layers.Flatten слой , чтобы сгладить результаты dots слоя в логит.

С помощью подклассовой модели вы можете определить функцию call() которая принимает пары (target, context) которые затем могут быть переданы на соответствующий уровень внедрения. Перерисуйте context_embedding выполнить скалярное произведение с target_embedding и вернуть сплюснутый результат.

class Word2Vec(Model):
  def __init__(self, vocab_size, embedding_dim):
    super(Word2Vec, self).__init__()
    self.target_embedding = Embedding(vocab_size,
                                      embedding_dim,
                                      input_length=1,
                                      name="w2v_embedding")
    self.context_embedding = Embedding(vocab_size,
                                       embedding_dim,
                                       input_length=num_ns+1)
    self.dots = Dot(axes=(3, 2))
    self.flatten = Flatten()

  def call(self, pair):
    target, context = pair
    word_emb = self.target_embedding(target)
    context_emb = self.context_embedding(context)
    dots = self.dots([context_emb, word_emb])
    return self.flatten(dots)

Определите функцию потерь и скомпилируйте модель

Для простоты вы можете использовать tf.keras.losses.CategoricalCrossEntropy в качестве альтернативы отрицательной потере выборки. Если вы хотите написать свою собственную функцию потерь, вы также можете сделать это следующим образом:

def custom_loss(x_logit, y_true):
      return tf.nn.sigmoid_cross_entropy_with_logits(logits=x_logit, labels=y_true)

Пришло время построить свою модель! Создайте экземпляр своего класса Word2Vec с размером встраивания 128 (вы можете поэкспериментировать с разными значениями). Скомпилируйте модель с tf.keras.optimizers.Adam оптимизатора tf.keras.optimizers.Adam .

embedding_dim = 128
word2vec = Word2Vec(vocab_size, embedding_dim)
word2vec.compile(optimizer='adam',
                 loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
                 metrics=['accuracy'])

Также определите обратный вызов для регистрации статистики обучения для tenorboard.

tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="logs")

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

word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20
63/63 [==============================] - 2s 11ms/step - loss: 1.6082 - accuracy: 0.2308
Epoch 2/20
63/63 [==============================] - 0s 5ms/step - loss: 1.5889 - accuracy: 0.5539
Epoch 3/20
63/63 [==============================] - 0s 5ms/step - loss: 1.5412 - accuracy: 0.6001
Epoch 4/20
63/63 [==============================] - 0s 5ms/step - loss: 1.4585 - accuracy: 0.5751
Epoch 5/20
63/63 [==============================] - 0s 5ms/step - loss: 1.3600 - accuracy: 0.5834
Epoch 6/20
63/63 [==============================] - 0s 5ms/step - loss: 1.2628 - accuracy: 0.6110
Epoch 7/20
63/63 [==============================] - 0s 5ms/step - loss: 1.1719 - accuracy: 0.6456
Epoch 8/20
63/63 [==============================] - 0s 5ms/step - loss: 1.0875 - accuracy: 0.6791
Epoch 9/20
63/63 [==============================] - 0s 5ms/step - loss: 1.0092 - accuracy: 0.7101
Epoch 10/20
63/63 [==============================] - 0s 5ms/step - loss: 0.9366 - accuracy: 0.7379
Epoch 11/20
63/63 [==============================] - 0s 5ms/step - loss: 0.8695 - accuracy: 0.7622
Epoch 12/20
63/63 [==============================] - 0s 5ms/step - loss: 0.8076 - accuracy: 0.7848
Epoch 13/20
63/63 [==============================] - 0s 5ms/step - loss: 0.7507 - accuracy: 0.8050
Epoch 14/20
63/63 [==============================] - 0s 5ms/step - loss: 0.6985 - accuracy: 0.8217
Epoch 15/20
63/63 [==============================] - 0s 5ms/step - loss: 0.6507 - accuracy: 0.8368
Epoch 16/20
63/63 [==============================] - 0s 5ms/step - loss: 0.6071 - accuracy: 0.8506
Epoch 17/20
63/63 [==============================] - 0s 5ms/step - loss: 0.5673 - accuracy: 0.8633
Epoch 18/20
63/63 [==============================] - 0s 5ms/step - loss: 0.5311 - accuracy: 0.8741
Epoch 19/20
63/63 [==============================] - 0s 5ms/step - loss: 0.4981 - accuracy: 0.8842
Epoch 20/20
63/63 [==============================] - 0s 5ms/step - loss: 0.4681 - accuracy: 0.8936
<tensorflow.python.keras.callbacks.History at 0x7f120c5b5210>

Tensorboard теперь показывает точность и потери модели Word2Vec.

%tensorboard --logdir logs

Встраивание поиска и анализа

Получите веса из модели с помощью get_layer() и get_weights() . Функция get_vocabulary() предоставляет словарь для создания файла метаданных с одним токеном на строку.

weights = word2vec.get_layer('w2v_embedding').get_weights()[0]
vocab = vectorize_layer.get_vocabulary()

Создайте и сохраните файлы векторов и метаданных.

out_v = io.open('vectors.tsv', 'w', encoding='utf-8')
out_m = io.open('metadata.tsv', 'w', encoding='utf-8')

for index, word in enumerate(vocab):
  if index == 0:
    continue  # skip 0, it's padding.
  vec = weights[index]
  out_v.write('\t'.join([str(x) for x in vec]) + "\n")
  out_m.write(word + "\n")
out_v.close()
out_m.close()

Загрузите vectors.tsv и metadata.tsv чтобы проанализировать полученные вложения в проекторе вложений.

try:
  from google.colab import files
  files.download('vectors.tsv')
  files.download('metadata.tsv')
except Exception:
  pass

Следующие шаги

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