¡El Día de la Comunidad de ML es el 9 de noviembre! Únase a nosotros para recibir actualizaciones de TensorFlow, JAX, y más Más información

Word2Vec

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

Word2Vec no es un algoritmo singular, más bien, es una familia de arquitecturas de modelos y optimizaciones que se pueden usar para aprender incrustaciones de palabras de grandes conjuntos de datos. Las incorporaciones aprendidas a través de Word2Vec han demostrado ser exitosas en una variedad de tareas posteriores de procesamiento del lenguaje natural.

Estos artículos propusieron dos métodos para aprender representaciones de palabras:

  • Continua modelo bolsa de palabras que predice la palabra central basado en las palabras de contexto circundante. El contexto consta de unas pocas palabras antes y después de la palabra actual (intermedia). Esta arquitectura se denomina modelo de bolsa de palabras, ya que el orden de las palabras en el contexto no es importante.
  • Saltar continua gramos modelo que predice palabras dentro de un rango determinado antes y después de la palabra actual en la misma frase. A continuación se ofrece un ejemplo práctico de esto.

Utilizará el enfoque de omisión de gramática en este tutorial. Primero, explorará los saltos-gramas y otros conceptos usando una sola oración como ilustración. A continuación, entrenará su propio modelo de Word2Vec en un pequeño conjunto de datos. Este tutorial también contiene código para exportar las incrustaciones entrenados y visualizarlos en el TensorFlow incrustación de proyector .

Salto de gramo y muestreo negativo

Mientras que un modelo de bolsa de palabras predice una palabra dado el contexto vecino, un modelo de omisión predice el contexto (o vecinos) de una palabra, dada la palabra en sí. El modelo se entrena en saltos-gramos, que son n-gramas que permiten omitir tokens (consulte 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 skip-gramo de (target_word, context_word) donde context_word aparece en el contexto vecina de target_word .

Considere la siguiente oración de 8 palabras.

El ancho camino relucía bajo el sol ardiente.

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 lapso de palabras a ambos lados de un target_word que se puede considerar context word . Eche un vistazo a esta tabla de omisiones para las palabras objetivo basadas en diferentes tamaños de ventana.

word2vec_skipgrams

El objetivo de entrenamiento del modelo de omisión de gramática 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 log media

word2vec_skipgram_objective

donde c es el tamaño del contexto de formación. La formulación básica de omisión de gramo define esta probabilidad utilizando la función softmax.

word2vec_full_softmax

donde V y V 'son objetivo y el vector de contexto representaciones de palabras y W es el tamaño del vocabulario.

Cálculo del denominador de esta formulación implica la realización de un softmax total sobre la totalidad de las palabras de vocabulario que a menudo es grande (10 5 -10 7) términos.

El contrastivo estimación del ruido función de pérdida es una aproximación eficiente para una softmax completa. Con el objetivo de aprender incrustaciones de palabras en lugar de modelar la palabra distribución, pérdida NCE puede simplificarse a utilizar el muestreo negativo.

El negativo simplificado muestreo objetivo para una palabra objetivo es distinguir la palabra contexto a partir de muestras num_ns negativas extraídas de distribución de ruido P n (w) de las palabras. Más precisamente, una aproximación eficiente de la plena softmax el vocabulario es, por un par skip-gramo, planteando la pérdida para una palabra objetivo como un problema de clasificación entre la palabra contexto y num_ns muestras negativas.

Una muestra negativa se define como un (target_word, context_word) par tal que el context_word no aparece en la window_size barrio de la target_word. Por la frase ejemplo, estos son pocas muestras potenciales negativos (cuando window_size es 2).

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

En la siguiente sección, generará omisiones 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:
The wide road shimmered in the hot sun.

Tokeniza 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 sentencia.

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

Generar saltos de gramos a partir de una oración

El tf.keras.preprocessing.sequence módulo proporciona funciones útiles que de preparación de datos Simplificar para Word2Vec. Puede utilizar los tf.keras.preprocessing.sequence.skipgrams para generar pares skip-gram de la example_sequence con un dado window_size de tokens en el intervalo [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

Eche un vistazo a algunos saltos-gramos positivos.

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

Muestreo negativo para un salto de gramo

Los skipgrams función devuelve todos los pares skip-gram positivas por deslizamiento en un lapso de ventana dada. Para producir pares de saltos de gramo adicionales que sirvan como muestras negativas para el entrenamiento, necesita tomar muestras de palabras aleatorias del vocabulario. Usar la tf.random.log_uniform_candidate_sampler función para la muestra num_ns número de muestras negativas para una palabra objetivo determinado 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 una positiva dada (target_word, context_word) skip-gramo, que ahora también tiene num_ns palabras de contexto muestra negativos que no aparecen en la vecindad tamaño de la ventana de target_word . Lotes los 1 positivas context_word y num_ns negativos palabras de contexto en un solo tensor. Esto produce un conjunto de SKIP-gramos positivos (etiquetado como 1 ) y las muestras negativas (etiquetado como 0 ) para cada palabra objetivo.

# 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)

Eche un vistazo al contexto y las etiquetas correspondientes para la palabra de destino del ejemplo de omisión de gramática 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    : 3
target_word     : road
context_indices : [1 2 1 4 3]
context_words   : ['the', 'wide', 'the', 'shimmered', 'road']
label           : [1 0 0 0 0]

Una tupla de (target, context, label) tensores constituye ejemplo una formación para la formación de su skip-gram negativo muestreo modelo Word2Vec. Tenga en cuenta que el objetivo es de forma (1,) mientras que el contexto y la etiqueta son de forma (1+num_ns,)

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

Resumen

Esta imagen resume el procedimiento de generar un ejemplo de entrenamiento a partir de una oración.

word2vec_negative_sampling

Compile todos los pasos en una función

Tabla de muestreo de saltos de gramos

Un conjunto de datos grande significa un vocabulario más amplio con un mayor número de palabras más frecuentes, como palabras vacías. Ejemplos de entrenamiento obtenidos del muestreo de palabras que ocurren comúnmente (como the , is , on ) no agregar mucha información útil para el modelo del que aprender. Mikolov y col. sugiera el submuestreo de palabras frecuentes como una práctica útil para mejorar la calidad de la incrustación.

El tf.keras.preprocessing.sequence.skipgrams función acepta un argumento tabla de muestreo a las probabilidades codifican de muestreo de cualquier token. Se puede utilizar el tf.keras.preprocessing.sequence.make_sampling_table para generar una tabla de muestreo probabilístico basado en el rango de frecuencia de palabras y pasarlo a skipgrams función. Echar un vistazo a 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 muestreo de la i-ésima palabra más común en un conjunto de datos. La función asume una distribución de Zipf de la palabra para las frecuencias de muestreo.

Genera 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. Observe que la tabla de muestreo se crea antes del muestreo de pares de palabras de omisión de gramática. 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 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

Preparar datos de entrenamiento para Word2Vec

Con una comprensión de cómo trabajar con una oración para un modelo de Word2Vec basado en muestreo de omisión de gramática negativa, puede proceder a generar ejemplos de capacitación 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 y observe 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.

Utilice las líneas no vacías para construir un tf.data.TextLineDataset objeto 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

Se puede utilizar el TextVectorization capa de vectorizar frases del corpus. Más información sobre el uso de esta capa en esta clasificación de texto tutorial. Observe en las primeras oraciones anteriores que el texto debe estar en un caso y la puntuación debe eliminarse. Para ello, definir una custom_standardization function que se puede utilizar 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 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 output_sequence_length length to pad all samples to same length.
vectorize_layer = layers.TextVectorization(
    standardize=custom_standardization,
    max_tokens=vocab_size,
    output_mode='int',
    output_sequence_length=sequence_length)

Llame a adapt en el conjunto de datos de texto para crear el vocabulario.

vectorize_layer.adapt(text_ds.batch(1024))

Una vez que el estado de la capa ha sido adaptada para representar el corpus de texto, el vocabulario se puede acceder con 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']

El vectorize_layer ahora se puede utilizar para generar vectores para cada elemento en los text_ds .

# 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 frases enteros codificados. Para preparar el conjunto de datos para entrenar un modelo de Word2Vec, acople 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

Echar un vistazo a 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', '', '', '', '', '', '', '', '']

Genere ejemplos de entrenamiento a partir de secuencias

sequences es ahora una lista de frases int codificada. Sólo tiene que llamar la generate_training_data() función definida anteriormente para generar los 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, representando el número total de ejemplos de entrenamiento.

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:33<00:00, 976.91it/s]
targets.shape: (64889,)
contexts.shape: (64889, 5)
labels.shape: (64889, 5)

Configurar el conjunto de datos para el rendimiento

Para llevar a cabo la dosificación eficaz para el número potencialmente elevado de ejemplos de entrenamiento, utilice el tf.data.Dataset API. Después de este paso, usted tendría una tf.data.Dataset objeto (target_word, context_word), (label) elementos para entrenar el 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 shapes: (((1024,), (1024, 5)), (1024, 5)), types: ((tf.int64, tf.int64), tf.int64)>

Añadir cache() y prefetch() para mejorar el rendimiento.

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

Modelo y formación

El modelo Word2Vec se puede implementar como un clasificador para distinguir entre palabras de contexto verdaderas de salta-gramas y palabras de contexto falsas obtenidas mediante muestreo negativo. Puede realizar un producto escalar entre las incrustaciones de palabras objetivo y de contexto para obtener predicciones para etiquetas y calcular la pérdida frente a etiquetas verdaderas en el conjunto de datos.

Modelo de Word2Vec en subclases

Utilice la API Keras subclases para definir su modelo Word2Vec con las siguientes capas:

  • target_embedding : Un tf.keras.layers.Embedding capa que busca la incorporación de una palabra cuando aparece como una palabra objetivo. El número de parámetros de esta capa son (vocab_size * embedding_dim) .
  • context_embedding : Otro tf.keras.layers.Embedding capa que busca la incorporación de una palabra cuando aparece como una palabra contexto. El número de parámetros de esta capa son los mismos que los de target_embedding , es decir, (vocab_size * embedding_dim) .
  • dots : A tf.keras.layers.Dot capa que calcula el producto escalar de objetivo y de contexto incrustaciones partir de un par de formación.
  • flatten : A tf.keras.layers.Flatten capa para aplanar los resultados de dots capa en logits.

Con el modelo de subclase, se puede definir la call() función que acepta (target, context) pares que luego se pueden pasar en su capa de encaje correspondiente. Cambiar la forma de la context_embedding para realizar un producto de punto con target_embedding y devolver el resultado aplanada.

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

Definir la función de pérdida y compilar el modelo

Para simplificar, se puede utilizar tf.keras.losses.CategoricalCrossEntropy como una alternativa a la pérdida de muestreo negativo. 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 de Word2Vec con una dimensión de incrustación de 128 (puede experimentar con diferentes valores). Compilar el modelo con el tf.keras.optimizers.Adam optimizador.

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 defina una devolución de llamada para registrar estadísticas de entrenamiento para tensorboard.

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

Entrenar el modelo con dataset preparado anteriormente para algún número de épocas.

word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20
63/63 [==============================] - 1s 9ms/step - loss: 1.6083 - accuracy: 0.2309
Epoch 2/20
63/63 [==============================] - 0s 2ms/step - loss: 1.5890 - accuracy: 0.5520
Epoch 3/20
63/63 [==============================] - 0s 3ms/step - loss: 1.5413 - accuracy: 0.6021
Epoch 4/20
63/63 [==============================] - 0s 2ms/step - loss: 1.4584 - accuracy: 0.5789
Epoch 5/20
63/63 [==============================] - 0s 2ms/step - loss: 1.3598 - accuracy: 0.5857
Epoch 6/20
63/63 [==============================] - 0s 2ms/step - loss: 1.2622 - accuracy: 0.6127
Epoch 7/20
63/63 [==============================] - 0s 2ms/step - loss: 1.1710 - accuracy: 0.6456
Epoch 8/20
63/63 [==============================] - 0s 2ms/step - loss: 1.0867 - accuracy: 0.6804
Epoch 9/20
63/63 [==============================] - 0s 3ms/step - loss: 1.0085 - accuracy: 0.7123
Epoch 10/20
63/63 [==============================] - 0s 2ms/step - loss: 0.9361 - accuracy: 0.7418
Epoch 11/20
63/63 [==============================] - 0s 2ms/step - loss: 0.8690 - accuracy: 0.7669
Epoch 12/20
63/63 [==============================] - 0s 2ms/step - loss: 0.8070 - accuracy: 0.7891
Epoch 13/20
63/63 [==============================] - 0s 2ms/step - loss: 0.7500 - accuracy: 0.8082
Epoch 14/20
63/63 [==============================] - 0s 3ms/step - loss: 0.6977 - accuracy: 0.8249
Epoch 15/20
63/63 [==============================] - 0s 3ms/step - loss: 0.6498 - accuracy: 0.8393
Epoch 16/20
63/63 [==============================] - 0s 3ms/step - loss: 0.6061 - accuracy: 0.8528
Epoch 17/20
63/63 [==============================] - 0s 3ms/step - loss: 0.5663 - accuracy: 0.8651
Epoch 18/20
63/63 [==============================] - 0s 3ms/step - loss: 0.5300 - accuracy: 0.8762
Epoch 19/20
63/63 [==============================] - 0s 2ms/step - loss: 0.4970 - accuracy: 0.8858
Epoch 20/20
63/63 [==============================] - 0s 2ms/step - loss: 0.4670 - accuracy: 0.8947
<keras.callbacks.History at 0x7fbea4362490>

Tensorboard ahora muestra la precisión y la pérdida del modelo Word2Vec.

%tensorboard --logdir logs

Incorporación de búsqueda y análisis

Obtener los pesos del modelo usando get_layer() y get_weights() . El get_vocabulary() función proporciona el vocabulario para construir un archivo de metadatos con una ficha por cada línea.

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

Cree y guarde los vectores y el archivo 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()

Descargar el vectors.tsv y metadata.tsv para analizar las inclusiones obtenidas en la incrustación de proyector .

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 de omisión de gramática con muestreo negativo desde cero y visualizar las incrustaciones de palabras obtenidas.