![]() | ![]() | ![]() | ![]() |
word2vec — это не отдельный алгоритм, а скорее семейство модельных архитектур и оптимизаций, которые можно использовать для изучения встраивания слов из больших наборов данных. Вложения, изученные с помощью word2vec, оказались успешными в различных последующих задачах обработки естественного языка.
В этих статьях предложено два метода изучения представлений слов:
- Непрерывная модель мешка слов : предсказывает среднее слово на основе слов окружающего контекста. Контекст состоит из нескольких слов до и после текущего (среднего) слова. Эта архитектура называется моделью мешка слов, поскольку порядок слов в контексте не важен.
- Непрерывная модель пропуска грамм : предсказывает слова в определенном диапазоне до и после текущего слова в том же предложении. Рабочий пример этого приведен ниже.
В этом руководстве вы будете использовать метод пропуска грамм. Во-первых, вы изучите скип-граммы и другие понятия, используя для иллюстрации одно предложение. Далее вы обучите свою собственную модель word2vec на небольшом наборе данных. Этот туториал также содержит код для экспорта обученных эмбеддингов и их визуализации в TensorFlow Embedding Projector .
Skip-gram и отрицательная выборка
В то время как модель мешка слов предсказывает слово с учетом соседнего контекста, модель пропуска грамм предсказывает контекст (или соседей) слова с учетом самого слова. Модель обучается на скип-граммах, которые представляют собой n-граммы, позволяющие пропускать токены (см. пример на диаграмме ниже). Контекст слова может быть представлен набором пар (target_word, context_word)
где context_word
появляется в соседнем контексте target_word
.
Рассмотрим следующее предложение из восьми слов:
Широкая дорога блестела на жарком солнце.
Слова контекста для каждого из 8 слов этого предложения определяются размером окна. Размер окна определяет диапазон слов по обе стороны от target_word
, который можно считать context word
. Ниже приведена таблица скип-грамм для целевых слов в зависимости от размера окна.
Целью обучения модели пропуска граммы является максимизация вероятности предсказания контекстных слов с учетом целевого слова. Для последовательности слов w 1 , w 2 , ... w T цель может быть записана как средняя логарифмическая вероятность
где c
— размер обучающего контекста. Базовая формулировка пропуска грамм определяет эту вероятность с помощью функции softmax.
где v и v ' являются целевым и контекстным векторным представлением слов, а W - размер словаря.
Вычисление знаменателя этой формулировки включает в себя выполнение полного softmax для всего словаря слов, которые часто являются большими (10 5 -10 7 ) терминами.
Функция потерь шумовой контрастной оценки (NCE) является эффективным приближением для полного 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 tqdm
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
# Load the TensorBoard notebook extension
%load_ext tensorboard
SEED = 42
AUTOTUNE = tf.data.AUTOTUNE
Векторизовать пример предложения
Рассмотрим следующее предложение:
Широкая дорога блестела на жарком солнце.
Обозначьте предложение:
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
для генерации пар skip-gram из 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]})")
(2, 3): (wide, road) (5, 3): (in, road) (4, 2): (shimmered, wide) (1, 7): (the, sun) (4, 1): (shimmered, the)
Отрицательная выборка для одного скип-грамма
Функция skipgrams
возвращает все положительные пары skip-gram путем скольжения по заданному диапазону окна. Чтобы создать дополнительные пары скип-грамм, которые будут служить отрицательными образцами для обучения, вам нужно выбрать случайные слова из словаря. Используйте функцию tf.random.log_uniform_candidate_sampler
для выборки num_ns
числа отрицательных выборок для заданного целевого слова в окне. Вы можете вызвать функцию для одного целевого слова skip-grams и передать контекстное слово как истинный класс, чтобы исключить его из выборки.
# 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)
скип-граммы теперь у вас также есть num_ns
отрицательных выборочных контекстных слов, которые не появляются в окрестности размера окна target_word
. Объедините 1
положительное context_word
и num_ns
слов отрицательного контекста в один тензор. Это создает набор положительных скип-грамм (помеченных как 1
) и отрицательных выборок (помеченных как 0
) для каждого целевого слова.
# Add a dimension so you can use concatenation (in the next step).
negative_sampling_candidates = tf.expand_dims(negative_sampling_candidates, 1)
# Concatenate a positive context word with negative sampled words.
context = tf.concat([context_class, negative_sampling_candidates], 0)
# Label the first context word as `1` (positive) followed by `num_ns` `0`s (negative).
label = tf.constant([1] + [0]*num_ns, dtype="int64")
# Reshape the 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 : 2 target_word : wide context_indices : [3 2 1 4 3] context_words : ['road', '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(2, shape=(), dtype=int32) context : tf.Tensor([3 2 1 4 3], shape=(5,), dtype=int64) label : tf.Tensor([1 0 0 0 0], shape=(5,), dtype=int64)
Резюме
На этой диаграмме показана процедура создания обучающего примера из предложения:
Обратите внимание, что слова temperature
и code
не являются частью входного предложения. Они принадлежат словарю, как и некоторые другие индексы, используемые на диаграмме выше.
Скомпилируйте все шаги в одну функцию
Таблица выборки скип-граммов
Большой набор данных означает больший словарный запас с большим количеством более частых слов, таких как стоп-слова. Обучающие примеры, полученные путем выборки часто встречающихся слов (таких 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 the 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 a 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 1130496/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
для следующих шагов:
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 the number of words in a sequence.
vocab_size = 4096
sequence_length = 10
# Use the `TextVectorization` layer to normalize, split, and map strings to
# integers. Set the `output_sequence_length` length to pad all samples to the
# same length.
vectorize_layer = layers.TextVectorization(
standardize=custom_standardization,
max_tokens=vocab_size,
output_mode='int',
output_sequence_length=sequence_length)
Вызовите TextVectorization.adapt
для набора текстовых данных, чтобы создать словарь.
vectorize_layer.adapt(text_ds.batch(1024))
Как только состояние слоя будет адаптировано для представления текстового корпуса, доступ к словарю можно получить с помощью TextVectorization.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
( tf.data.Dataset
). Примените Dataset.batch
, Dataset.prefetch
, Dataset.map
и Dataset.unbatch
.
# 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)
targets = np.array(targets)
contexts = np.array(contexts)[:,:,0]
labels = np.array(labels)
print('\n')
print(f"targets.shape: {targets.shape}")
print(f"contexts.shape: {contexts.shape}")
print(f"labels.shape: {labels.shape}")
100%|██████████| 32777/32777 [00:40<00:00, 811.35it/s] targets.shape: (66005,) contexts.shape: (66005, 5) labels.shape: (66005, 5)
Настройте набор данных для производительности
Чтобы выполнить эффективную пакетную обработку потенциально большого количества обучающих примеров, используйте API tf.data.Dataset
. После этого шага у вас будет объект 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 element_spec=((TensorSpec(shape=(1024,), dtype=tf.int64, name=None), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None)), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None))>
Примените Dataset.cache
и Dataset.prefetch
для повышения производительности:
dataset = dataset.cache().prefetch(buffer_size=AUTOTUNE)
print(dataset)
<PrefetchDataset element_spec=((TensorSpec(shape=(1024,), dtype=tf.int64, name=None), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None)), TensorSpec(shape=(1024, 5), dtype=tf.int64, name=None))>
Модель и обучение
Модель word2vec может быть реализована как классификатор для различения слов истинного контекста из скип-грамм и слов ложного контекста, полученных посредством отрицательной выборки. Вы можете выполнить умножение скалярного произведения между вложениями целевых и контекстных слов, чтобы получить прогнозы для меток и вычислить функцию потерь для истинных меток в наборе данных.
Подкласс модели word2vec
Используйте Keras Subclassing API , чтобы определить модель word2vec со следующими слоями:
-
target_embedding
: слойtf.keras.layers.Embedding
, который ищет встраивание слова, когда оно появляется как целевое слово. Количество параметров в этом слое(vocab_size * embedding_dim)
. -
context_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(tf.keras.Model):
def __init__(self, vocab_size, embedding_dim):
super(Word2Vec, self).__init__()
self.target_embedding = layers.Embedding(vocab_size,
embedding_dim,
input_length=1,
name="w2v_embedding")
self.context_embedding = layers.Embedding(vocab_size,
embedding_dim,
input_length=num_ns+1)
def call(self, pair):
target, context = pair
# target: (batch, dummy?) # The dummy axis doesn't exist in TF2.7+
# context: (batch, context)
if len(target.shape) == 2:
target = tf.squeeze(target, axis=1)
# target: (batch,)
word_emb = self.target_embedding(target)
# word_emb: (batch, embed)
context_emb = self.context_embedding(context)
# context_emb: (batch, context, embed)
dots = tf.einsum('be,bce->bc', word_emb, context_emb)
# dots: (batch, context)
return 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
.
embedding_dim = 128
word2vec = Word2Vec(vocab_size, embedding_dim)
word2vec.compile(optimizer='adam',
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
Также определите обратный вызов для регистрации статистики обучения для Tensorboard:
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="logs")
Обучите модель на dataset
для некоторого количества эпох:
word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20 64/64 [==============================] - 1s 4ms/step - loss: 1.6081 - accuracy: 0.2343 Epoch 2/20 64/64 [==============================] - 0s 3ms/step - loss: 1.5878 - accuracy: 0.5475 Epoch 3/20 64/64 [==============================] - 0s 3ms/step - loss: 1.5381 - accuracy: 0.5813 Epoch 4/20 64/64 [==============================] - 0s 3ms/step - loss: 1.4545 - accuracy: 0.5620 Epoch 5/20 64/64 [==============================] - 0s 3ms/step - loss: 1.3567 - accuracy: 0.5764 Epoch 6/20 64/64 [==============================] - 0s 3ms/step - loss: 1.2603 - accuracy: 0.6070 Epoch 7/20 64/64 [==============================] - 0s 3ms/step - loss: 1.1703 - accuracy: 0.6403 Epoch 8/20 64/64 [==============================] - 0s 3ms/step - loss: 1.0866 - accuracy: 0.6756 Epoch 9/20 64/64 [==============================] - 0s 3ms/step - loss: 1.0090 - accuracy: 0.7087 Epoch 10/20 64/64 [==============================] - 0s 3ms/step - loss: 0.9368 - accuracy: 0.7371 Epoch 11/20 64/64 [==============================] - 0s 3ms/step - loss: 0.8699 - accuracy: 0.7631 Epoch 12/20 64/64 [==============================] - 0s 3ms/step - loss: 0.8081 - accuracy: 0.7849 Epoch 13/20 64/64 [==============================] - 0s 3ms/step - loss: 0.7512 - accuracy: 0.8052 Epoch 14/20 64/64 [==============================] - 0s 3ms/step - loss: 0.6991 - accuracy: 0.8230 Epoch 15/20 64/64 [==============================] - 0s 3ms/step - loss: 0.6514 - accuracy: 0.8378 Epoch 16/20 64/64 [==============================] - 0s 3ms/step - loss: 0.6079 - accuracy: 0.8517 Epoch 17/20 64/64 [==============================] - 0s 3ms/step - loss: 0.5683 - accuracy: 0.8641 Epoch 18/20 64/64 [==============================] - 0s 3ms/step - loss: 0.5322 - accuracy: 0.8747 Epoch 19/20 64/64 [==============================] - 0s 3ms/step - loss: 0.4994 - accuracy: 0.8844 Epoch 20/20 64/64 [==============================] - 0s 3ms/step - loss: 0.4695 - accuracy: 0.8935 <keras.callbacks.History at 0x7fc21c237050>
Tensorboard теперь показывает точность и потери модели word2vec:
#docs_infra: no_execute
%tensorboard --logdir logs
Встраивание поиска и анализа
Получите веса из модели, используя Model.get_layer
и Layer.get_weights
. Функция TextVectorization.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
для анализа полученных вложений в Embedding Projector :
try:
from google.colab import files
files.download('vectors.tsv')
files.download('metadata.tsv')
except Exception:
pass
Следующие шаги
В этом руководстве показано, как реализовать модель word2vec с пропуском грамматики с отрицательной выборкой с нуля и визуализировать полученные вложения слов.
Чтобы узнать больше о векторах слов и их математических представлениях, обратитесь к этим примечаниям .
Чтобы узнать больше о расширенной обработке текста, прочитайте учебник по модели Transformer для понимания языка .
Если вас интересуют предварительно обученные модели встраивания, вас также может заинтересовать Exploring the TF-Hub CORD-19 Swivel Embeddings или Multilingual Universal Sentence Encoder .
Вы также можете обучить модель на новом наборе данных (их много доступно в наборах данных TensorFlow ).