![]() | ![]() | ![]() | ![]() |
word2vec no es un algoritmo singular, sino una familia de arquitecturas modelo y optimizaciones que se pueden usar para aprender incrustaciones de palabras a partir de grandes conjuntos de datos. Las incrustaciones aprendidas a través de word2vec han demostrado ser exitosas en una variedad de tareas de procesamiento de lenguaje natural posteriores.
Estos artículos propusieron dos métodos para aprender las representaciones de las palabras:
- Modelo continuo de bolsa de palabras : predice la palabra del medio en función de las palabras del contexto circundante. El contexto consta de unas pocas palabras antes y después de la palabra actual (en el medio). Esta arquitectura se denomina modelo de bolsa de palabras, ya que el orden de las palabras en el contexto no es importante.
- Modelo de salto de gramo continuo : predice palabras dentro de un cierto rango antes y después de la palabra actual en la misma oración. Un ejemplo trabajado de esto se da a continuación.
En este tutorial, usará el método skip-gram. Primero, explorará skip-grams y otros conceptos usando una sola oración como ilustración. A continuación, entrenará su propio modelo word2vec en un pequeño conjunto de datos. Este tutorial también contiene código para exportar las incrustaciones entrenadas y visualizarlas en TensorFlow Embedding Projector .
Skip-gram y muestreo negativo
Mientras que un modelo de bolsa de palabras predice una palabra dado el contexto vecino, un modelo skip-gram predice el contexto (o vecinos) de una palabra, dada la palabra misma. El modelo está entrenado en skip-grams, que son n-grams que permiten omitir tokens (vea el diagrama a continuación para ver un ejemplo). El contexto de una palabra se puede representar a través de un conjunto de pares de omisión de gramo (target_word, context_word)
donde context_word
aparece en el contexto vecino de target_word
.
Considere la siguiente oración de ocho palabras:
El ancho camino brillaba bajo el sol abrasador.
Las palabras de contexto para cada una de las 8 palabras de esta oración están definidas por un tamaño de ventana. El tamaño de la ventana determina el intervalo de palabras a ambos lados de target_word
que puede considerarse una context word
. A continuación se muestra una tabla de saltos de gramo para las palabras de destino en función de diferentes tamaños de ventana.
El objetivo de entrenamiento del modelo skip-gram es maximizar la probabilidad de predecir palabras de contexto dada la palabra objetivo. Para una secuencia de palabras w 1 , w 2 , ... w T , el objetivo se puede escribir como la probabilidad logarítmica promedio
donde c
es el tamaño del contexto de entrenamiento. La formulación básica de skip-gram define esta probabilidad usando la función softmax.
donde v y v ' son representaciones de vector objetivo y de contexto de palabras y W es el tamaño del vocabulario.
Calcular el denominador de esta formulación implica realizar un softmax completo sobre todas las palabras del vocabulario, que a menudo son términos grandes (10 5 -10 7 ).
La función de pérdida de estimación contrastiva de ruido (NCE) es una aproximación eficiente para un softmax completo. Con el objetivo de aprender incrustaciones de palabras en lugar de modelar la distribución de palabras, la pérdida de NCE se puede simplificar para usar un muestreo negativo.
El objetivo de muestreo negativo simplificado para una palabra objetivo es distinguir la palabra de contexto de num_ns
muestras negativas extraídas de la distribución de ruido Pn (w) de palabras. Más precisamente, una aproximación eficiente de softmax completo sobre el vocabulario es, para un par de saltos de gramo, plantear la pérdida de una palabra objetivo como un problema de clasificación entre la palabra de contexto y num_ns
muestras negativas.
Una muestra negativa se define como un (target_word, context_word)
tal que context_word
no aparece en la vecindad window_size
de target_word
. Para la oración de ejemplo, estas son algunas muestras negativas potenciales (cuando window_size
es 2
).
(hot, shimmered)
(wide, hot)
(wide, sun)
En la siguiente sección, generará skip-grams y muestras negativas para una sola oración. También aprenderá sobre técnicas de submuestreo y entrenará un modelo de clasificación para ejemplos de entrenamiento positivos y negativos más adelante en el tutorial.
Configuración
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
Vectorizar una oración de ejemplo
Considere la siguiente oración:
El ancho camino brillaba bajo el sol abrasador.
Tokenizar la oración:
sentence = "The wide road shimmered in the hot sun"
tokens = list(sentence.lower().split())
print(len(tokens))
8
Cree un vocabulario para guardar asignaciones de tokens a índices enteros:
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}
Cree un vocabulario inverso para guardar asignaciones de índices enteros a tokens:
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'}
Vectoriza tu oración:
example_sequence = [vocab[word] for word in tokens]
print(example_sequence)
[1, 2, 3, 4, 5, 1, 6, 7]
Genera saltos de gramo a partir de una oración
El módulo tf.keras.preprocessing.sequence
proporciona funciones útiles que simplifican la preparación de datos para word2vec. Puede usar tf.keras.preprocessing.sequence.skipgrams
para generar pares de saltos de gramo a partir de example_sequence
con un window_size
dado a partir de tokens en el rango [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
Imprime algunos skip-grams positivos:
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)
Muestreo negativo para un skip-gram
La función skipgrams
devuelve todos los pares skip-gram positivos deslizándose sobre un intervalo de ventana determinado. Para producir pares de saltos de gramo adicionales que sirvan como muestras negativas para el entrenamiento, debe muestrear palabras aleatorias del vocabulario. Utilice la función tf.random.log_uniform_candidate_sampler
para muestrear num_ns
de muestras negativas para una palabra de destino determinada en una ventana. Puede llamar a la función en la palabra de destino de un skip-grams y pasar la palabra de contexto como clase verdadera para excluirla de la muestra.
# 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']
Construya un ejemplo de entrenamiento
Para un skip-gram positivo dado (target_word, context_word)
, ahora también tiene num_ns
palabras de contexto muestreadas negativas que no aparecen en la vecindad del tamaño de la ventana de target_word
. Reúna 1
context_word
positiva y num_ns
palabras de contexto negativas en un tensor. Esto produce un conjunto de skip-grams positivos (etiquetados como 1
) y muestras negativas (etiquetadas como 0
) para cada palabra objetivo.
# 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)
Consulte el contexto y las etiquetas correspondientes para la palabra de destino del ejemplo de salto de gramo anterior:
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]
Una tupla de tensores (target, context, label)
constituye un ejemplo de entrenamiento para entrenar su modelo word2vec de muestreo negativo skip-gram. Observe que el destino tiene forma (1,)
mientras que el contexto y la etiqueta tienen forma (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)
Resumen
Este diagrama resume el procedimiento para generar un ejemplo de entrenamiento a partir de una oración:
Observe que las palabras temperature
y code
no forman parte de la oración de entrada. Pertenecen al vocabulario como algunos otros índices utilizados en el diagrama anterior.
Compilar todos los pasos en una función
Tabla de muestreo de salto de gramo
Un conjunto de datos grande significa un vocabulario más grande con una mayor cantidad de palabras más frecuentes, como palabras vacías. Los ejemplos de entrenamiento obtenidos a partir de muestras de palabras comunes ( the
, is
, on
) no agregan mucha información útil para que el modelo aprenda. Mikolov et al. sugiera el submuestreo de palabras frecuentes como una práctica útil para mejorar la calidad de incrustación.
La función tf.keras.preprocessing.sequence.skipgrams
acepta un argumento de tabla de muestreo para codificar las probabilidades de muestrear cualquier token. Puede usar tf.keras.preprocessing.sequence.make_sampling_table
para generar una tabla de muestreo probabilístico basada en el rango de frecuencia de palabras y pasarla a la función skipgrams
. Inspeccione las probabilidades de muestreo para un vocab_size
de 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]
denota la probabilidad de muestrear la i-ésima palabra más común en un conjunto de datos. La función asume una distribución de Zipf de las frecuencias de palabras para el muestreo.
Generar datos de entrenamiento
Compile todos los pasos descritos anteriormente en una función que se pueda llamar en una lista de oraciones vectorizadas obtenidas de cualquier conjunto de datos de texto. Tenga en cuenta que la tabla de muestreo se construye antes de muestrear pares de palabras de salto de gramo. Utilizará esta función en las secciones posteriores.
# 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
Preparar datos de entrenamiento para word2vec
Con una comprensión de cómo trabajar con una oración para un modelo word2vec basado en muestreo negativo skip-gram, ¡puede proceder a generar ejemplos de entrenamiento a partir de una lista más grande de oraciones!
Descargar corpus de texto
Utilizará un archivo de texto de la escritura de Shakespeare para este tutorial. Cambie la siguiente línea para ejecutar este código en sus propios datos.
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
Lea el texto del archivo e imprima las primeras líneas:
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.
Use las líneas no vacías para construir un objeto tf.data.TextLineDataset
para los siguientes pasos:
text_ds = tf.data.TextLineDataset(path_to_file).filter(lambda x: tf.cast(tf.strings.length(x), bool))
Vectorizar oraciones del corpus
Puede usar la capa TextVectorization
para vectorizar oraciones del corpus. Obtenga más información sobre el uso de esta capa en este tutorial de clasificación de texto . Observe en las primeras oraciones anteriores que el texto debe estar en un caso y se debe eliminar la puntuación. Para hacer esto, defina una custom_standardization function
que se pueda usar en la capa 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)
Llame a TextVectorization.adapt
en el conjunto de datos de texto para crear vocabulario.
vectorize_layer.adapt(text_ds.batch(1024))
Una vez que el estado de la capa se ha adaptado para representar el corpus de texto, se puede acceder al vocabulario con TextVectorization.get_vocabulary
. Esta función devuelve una lista de todos los tokens de vocabulario ordenados (descendentemente) por su frecuencia.
# 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
ahora se puede usar para generar vectores para cada elemento en text_ds
(un tf.data.Dataset
). Aplique Dataset.batch
, Dataset.prefetch
, Dataset.map
y Dataset.unbatch
.
# Vectorize the data in text_ds.
text_vector_ds = text_ds.batch(1024).prefetch(AUTOTUNE).map(vectorize_layer).unbatch()
Obtener secuencias del conjunto de datos
Ahora tiene un tf.data.Dataset
de oraciones codificadas con enteros. Para preparar el conjunto de datos para entrenar un modelo word2vec, aplane el conjunto de datos en una lista de secuencias de vectores de oraciones. Este paso es necesario, ya que iteraría sobre cada oración en el conjunto de datos para producir ejemplos positivos y negativos.
sequences = list(text_vector_ds.as_numpy_iterator())
print(len(sequences))
32777
Inspeccione algunos ejemplos de 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', '', '', '', '', '', '', '', '']
Genera ejemplos de entrenamiento a partir de secuencias.
sequences
ahora es una lista de oraciones codificadas int. Simplemente llame a la función generate_training_data
definida anteriormente para generar ejemplos de entrenamiento para el modelo word2vec. En resumen, la función itera sobre cada palabra de cada secuencia para recopilar palabras de contexto positivas y negativas. La longitud del objetivo, los contextos y las etiquetas deben ser los mismos y representar el número total de ejemplos de capacitación.
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)
Configurar el conjunto de datos para el rendimiento
Para realizar un procesamiento por lotes eficiente para la cantidad potencialmente grande de ejemplos de capacitación, use la API tf.data.Dataset
. Después de este paso, tendría un objeto tf.data.Dataset
de (target_word, context_word), (label)
elementos para entrenar su modelo 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))>
Aplique Dataset.cache
y Dataset.prefetch
para mejorar el rendimiento:
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))>
modelo y entrenamiento
El modelo word2vec se puede implementar como un clasificador para distinguir entre palabras de contexto verdadero de skip-grams y palabras de contexto falso obtenidas mediante muestreo negativo. Puede realizar una multiplicación de producto punto entre las incrustaciones de palabras objetivo y de contexto para obtener predicciones para etiquetas y calcular la función de pérdida contra etiquetas verdaderas en el conjunto de datos.
Modelo word2vec subclasificado
Utilice la API de subclases de Keras para definir su modelo word2vec con las siguientes capas:
-
target_embedding
: una capatf.keras.layers.Embedding
, que busca la incrustación de una palabra cuando aparece como palabra objetivo. El número de parámetros en esta capa es(vocab_size * embedding_dim)
. -
context_embedding
: otra capatf.keras.layers.Embedding
, que busca la incrustación de una palabra cuando aparece como una palabra de contexto. El número de parámetros en esta capa es el mismo que el detarget_embedding
, es decir(vocab_size * embedding_dim)
. -
dots
: una capatf.keras.layers.Dot
que calcula el producto escalar de las incrustaciones de destino y contexto de un par de entrenamiento. -
flatten
: Una capatf.keras.layers.Flatten
para aplanar los resultados de la capa dedots
en logits.
Con el modelo subclasificado, puede definir la función call()
que acepta pares (target, context)
que luego se pueden pasar a su capa de incrustación correspondiente. context_embedding
para realizar un producto de punto con target_embedding
y devuelva el resultado aplanado.
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
Defina la función de pérdida y compile el modelo
Para simplificar, puede utilizar tf.keras.losses.CategoricalCrossEntropy
como alternativa a la pérdida de muestreo negativa. Si desea escribir su propia función de pérdida personalizada, también puede hacerlo de la siguiente manera:
def custom_loss(x_logit, y_true):
return tf.nn.sigmoid_cross_entropy_with_logits(logits=x_logit, labels=y_true)
¡Es hora de construir tu modelo! Cree una instancia de su clase word2vec con una dimensión de incrustación de 128 (podría experimentar con diferentes valores). Compile el modelo con el optimizador 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'])
También define una devolución de llamada para registrar estadísticas de entrenamiento para Tensorboard:
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="logs")
Entrene el modelo en el conjunto de dataset
para una cierta cantidad de épocas:
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 ahora muestra la precisión y la pérdida del modelo word2vec:
#docs_infra: no_execute
%tensorboard --logdir logs
Incorporación de búsqueda y análisis
Obtenga los pesos del modelo usando Model.get_layer
y Layer.get_weights
. La función TextVectorization.get_vocabulary
proporciona el vocabulario para crear un archivo de metadatos con un token por línea.
weights = word2vec.get_layer('w2v_embedding').get_weights()[0]
vocab = vectorize_layer.get_vocabulary()
Cree y guarde los vectores y los archivos de metadatos:
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()
Descarga los vectors.tsv
y metadata.tsv
para analizar las incrustaciones obtenidas en el Embedding Projector :
try:
from google.colab import files
files.download('vectors.tsv')
files.download('metadata.tsv')
except Exception:
pass
Próximos pasos
Este tutorial le ha mostrado cómo implementar un modelo word2vec skip-gram con muestreo negativo desde cero y visualizar las incrustaciones de palabras obtenidas.
Para obtener más información sobre los vectores de palabras y sus representaciones matemáticas, consulte estas notas .
Para obtener más información sobre el procesamiento de texto avanzado, lea el modelo de Transformer para el tutorial de comprensión del lenguaje .
Si está interesado en modelos de incrustación previamente entrenados, también puede interesarle Explorar las incrustaciones giratorias TF-Hub CORD-19 o el codificador de oraciones universal multilingüe .
También puede entrenar el modelo en un nuevo conjunto de datos (hay muchos disponibles en TensorFlow Datasets ).