Word2Vec

Voir sur TensorFlow.org Exécuter dans Google Colab Voir la source sur GitHub Télécharger le cahier

Word2Vec n'est pas un algorithme singulier, c'est plutôt une famille d'architectures de modèles et d'optimisations qui peuvent être utilisées pour apprendre les inclusions de mots à partir de grands ensembles de données. Les intégrations apprises via Word2Vec se sont avérées efficaces pour diverses tâches de traitement du langage naturel en aval.

Ces articles proposaient deux méthodes d'apprentissage des représentations des mots :

  • Continue-de-Sac mots modèle qui prédit le mot milieu en fonction des mots entourant contexte. Le contexte se compose de quelques mots avant et après le mot courant (au milieu). Cette architecture est appelée un modèle de sac de mots car l'ordre des mots dans le contexte n'est pas important.
  • Skip-gramme continu modèle qui prédisent des mots dans une certaine plage avant et après le mot en cours dans la même phrase. Un exemple travaillé de ceci est donné ci-dessous.

Vous utiliserez l'approche skip-gram dans ce didacticiel. Tout d'abord, vous explorerez les skip-grams et d'autres concepts en utilisant une seule phrase à titre d'illustration. Ensuite, vous entraînerez votre propre modèle Word2Vec sur un petit ensemble de données. Ce tutoriel contient également le code pour exporter les incorporations formés et les visualiser dans le tensorflow Embedding projecteur .

Skip-gram et échantillonnage négatif

Alors qu'un modèle de sac de mots prédit un mot étant donné le contexte voisin, un modèle de saut de gramme prédit le contexte (ou les voisins) d'un mot, étant donné le mot lui-même. Le modèle est entraîné sur des skip-grams, qui sont des n-grammes qui permettent de sauter des jetons (voir le diagramme ci-dessous pour un exemple). Le contexte d'un mot peut être représenté par un ensemble de paires skip-grammes de (target_word, context_word)context_word apparaît dans le contexte voisin de target_word .

Considérez la phrase suivante de 8 mots.

La large route scintillait sous le soleil brûlant.

Les mots de contexte pour chacun des 8 mots de cette phrase sont définis par une taille de fenêtre. La taille de la fenêtre détermine la durée des mots de chaque côté d'un target_word qui peut être considéré comme context word . Jetez un œil à ce tableau de skip-grams pour les mots cibles en fonction de différentes tailles de fenêtre.

word2vec_skipgrams

L'objectif d'apprentissage du modèle skip-gram est de maximiser la probabilité de prédire les mots de contexte étant donné le mot cible. Pour une séquence de mots w 1, w 2, ... w T, l'objectif peut être écrit comme la probabilité log moyenne

word2vec_skipgram_objective

c est la taille du contexte de formation. La formulation de base de skip-gram définit cette probabilité à l'aide de la fonction softmax.

word2vec_full_softmax

v et v 'sont des représentations cibles et vecteur de contexte de mots et W est la taille du vocabulaire.

Le calcul du dénominateur de cette formulation implique la réalisation d' une softmax complète sur l'ensemble des mots de vocabulaire qui est des termes souvent grand (10 5 -10 7).

Le bruit contrastive Estimation fonction de perte est une approximation efficace pour une softmax complète. Avec un objectif d'apprendre mot incorporations au lieu de modéliser la distribution des mots, la perte des RCE peut être simplifié à utiliser un échantillonnage négatif.

L'objectif négatif simplifié d' échantillonnage pour un mot cible est de distinguer le mot de contexte à partir d' échantillons de num_ns négatifs tirés de la distribution de bruit P n (w) de mots. Plus précisément, une approximation efficace de softmax complet sur le vocabulaire est, pour une paire saut-gramme, de poser la perte d'un mot cible comme un problème de classification entre le mot de contexte et num_ns échantillons négatifs.

Un échantillon négatif est défini comme un (target_word, context_word) de telle sorte que la paire context_word ne figure pas dans le window_size voisinage de la target_word. Pour la phrase d'exemple, ce sont quelques échantillons négatifs potentiels (quand window_size est 2).

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

Dans la section suivante, vous allez générer des skip-grammes et des échantillons négatifs pour une seule phrase. Vous découvrirez également les techniques de sous-échantillonnage et formerez un modèle de classification pour des exemples de formation positifs et négatifs plus tard dans le didacticiel.

Installer

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

Vectoriser une phrase d'exemple

Considérez la phrase suivante :
The wide road shimmered in the hot sun.

Tokenize la phrase :

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

Créez un vocabulaire pour enregistrer les mappages de jetons vers des indices entiers.

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}

Créez un vocabulaire inverse pour enregistrer les mappages d'indices entiers en jetons.

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'}

Vectorisez votre phrase.

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

Générer des skip-grams à partir d'une phrase

Le tf.keras.preprocessing.sequence module fournit des fonctions utiles qui simplifient l' préparation des données pour Word2Vec. Vous pouvez utiliser les tf.keras.preprocessing.sequence.skipgrams pour générer des paires de saut-gramme du example_sequence avec une donnée window_size de jetons dans l'intervalle [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

Jetez un œil à quelques saut-grammes positifs.

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

Echantillonnage négatif pour un skip-gramme

Les skipgrams fonction retourne toutes les paires skip-gram positifs en la glissant sur une période de fenêtre donnée. Pour produire des paires de sauts-grammes supplémentaires qui serviraient d'échantillons négatifs pour l'apprentissage, vous devez échantillonner des mots aléatoires du vocabulaire. Utilisez la tf.random.log_uniform_candidate_sampler fonction de l' échantillon num_ns nombre d'échantillons négatifs pour un mot cible donnée dans une fenêtre. Vous pouvez appeler la fonction sur le mot cible d'un skip-grams et passer le mot de contexte en tant que vraie classe pour l'exclure de l'échantillonnage.

# 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']

Construire un exemple de formation

Pour un positif donné (target_word, context_word) skip-gramme, vous avez maintenant aussi num_ns mots de contexte échantillonnées négatifs qui ne figurent pas dans le quartier de taille de la fenêtre de target_word . Lot les 1 positifs context_word et num_ns mots de contexte négatif dans un tenseur. On obtient ainsi un ensemble de saut-grammes positive (appelée 1 ) et des échantillons négatifs (appelée 0 ) pour chaque mot cible.

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

Jetez un œil au contexte et aux étiquettes correspondantes pour le mot cible de l'exemple de skip-gram ci-dessus.

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    : 4
target_word     : shimmered
context_indices : [3 2 1 4 3]
context_words   : ['road', 'wide', 'the', 'shimmered', 'road']
label           : [1 0 0 0 0]

Un tuple de (target, context, label) le (target, context, label) l' (target, context, label) tenseurs constitue un exemple de formation pour la formation de votre négatif skip-gramme d' échantillonnage modèle Word2Vec. Notez que la cible est de forme (1,) , tandis que le cadre et l' étiquette sont de forme (1+num_ns,)

print("target  :", target)
print("context :", context)
print("label   :", label)
target  : tf.Tensor(4, 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)

Sommaire

Cette image résume la procédure de génération d'exemple d'entraînement à partir d'une phrase.

word2vec_negative_sampling

Compilez toutes les étapes en une seule fonction

Tableau d'échantillonnage de saut de gramme

Un grand ensemble de données signifie un plus grand vocabulaire avec un nombre plus élevé de mots plus fréquents tels que des mots vides. Exemples de formation obtenus à partir d' échantillonnage des mots fréquemment rencontrés (tels que the , is , on ) ne pas ajouter beaucoup d' informations utiles pour le modèle d'apprendre. Mikolov et al. suggérer le sous-échantillonnage des mots fréquents comme pratique utile pour améliorer la qualité de l'intégration.

La tf.keras.preprocessing.sequence.skipgrams fonction accepte un argument de table d'échantillonnage à probabilités d'encodage de tout jeton d' échantillonnage. Vous pouvez utiliser le tf.keras.preprocessing.sequence.make_sampling_table pour générer une table d'échantillonnage probabiliste basé rang de mots de fréquence et le transmettre à skipgrams fonction. Jetez un oeil sur les probabilités d' échantillonnage pour une 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] désigne la probabilité de l' échantillonnage du i-ième mot le plus commun dans un ensemble de données. La fonction assume une de la distribution de Zipf des fréquences de mots pour l' échantillonnage.

Générer des données d'entraînement

Compilez toutes les étapes décrites ci-dessus dans une fonction qui peut être appelée sur une liste de phrases vectorisées obtenues à partir de n'importe quel ensemble de données de texte. Notez que la table d'échantillonnage est construite avant d'échantillonner les paires de mots saut-gramme. Vous utiliserez cette fonction dans les sections suivantes.

# 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

Préparer les données d'entraînement pour Word2Vec

Avec une compréhension de la façon de travailler avec une phrase pour un modèle Word2Vec basé sur un échantillonnage négatif de gramme de saut, vous pouvez générer des exemples d'entraînement à partir d'une plus grande liste de phrases !

Télécharger le corpus de texte

Vous utiliserez un fichier texte de l'écriture de Shakespeare pour ce tutoriel. Modifiez la ligne suivante pour exécuter ce code sur vos propres données.

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

Lisez le texte du fichier et examinez les premières lignes.

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.

Utilisez les lignes non vides pour construire un tf.data.TextLineDataset objet pour les étapes suivantes.

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

Vectoriser les phrases du corpus

Vous pouvez utiliser la TextVectorization couche vectoriser phrases du corpus. En savoir plus sur l' utilisation de cette couche dans cette classification de texte tutoriel. Remarquez dès les premières phrases ci-dessus que le texte doit être dans un seul cas et que la ponctuation doit être supprimée. Pour ce faire, définir une custom_standardization function qui peut être utilisé dans la couche 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 = layers.TextVectorization(
    standardize=custom_standardization,
    max_tokens=vocab_size,
    output_mode='int',
    output_sequence_length=sequence_length)

Appelez adapt sur l'ensemble de données de texte pour créer le vocabulaire.

vectorize_layer.adapt(text_ds.batch(1024))

Une fois que l'état de la couche a été adapté pour représenter le corpus de textes, le vocabulaire est accessible avec get_vocabulary() . Cette fonction renvoie une liste de tous les jetons de vocabulaire triés (décroissant) par leur fréquence.

# 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']

Le vectorize_layer peut maintenant être utilisé pour générer des vecteurs pour chaque élément dans les text_ds .

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

Obtenir des séquences à partir du jeu de données

Vous avez maintenant un tf.data.Dataset de phrases codées entier. Pour préparer l'ensemble de données pour l'apprentissage d'un modèle Word2Vec, aplatissez l'ensemble de données en une liste de séquences vectorielles de phrases. Cette étape est requise car vous parcourriez chaque phrase de l'ensemble de données pour produire des exemples positifs et négatifs.

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

Jetez un oeil à quelques exemples 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', '', '', '', '', '', '', '', '']

Générer des exemples d'entraînement à partir de séquences

sequences est maintenant une liste de phrases codées int. Il suffit d' appeler la generate_training_data() fonction définie précédemment pour générer des exemples de formation pour le modèle Word2Vec. Pour récapituler, la fonction itère sur chaque mot de chaque séquence pour collecter des mots de contexte positifs et négatifs. La longueur de la cible, les contextes et les étiquettes doivent être les mêmes, représentant le nombre total d'exemples de formation.

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:29<00:00, 1108.22it/s]
targets.shape: (65783,)
contexts.shape: (65783, 5)
labels.shape: (65783, 5)

Configurer l'ensemble de données pour les performances

Pour effectuer batching efficace pour le nombre potentiellement élevé d'exemples de formation, utilisez le tf.data.Dataset API. Après cette étape, vous auriez un tf.data.Dataset objet (target_word, context_word), (label) éléments pour former votre modèle 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)>

Ajouter le cache() et prefetch() pour améliorer les performances.

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

Modèle et formation

Le modèle Word2Vec peut être implémenté en tant que classificateur pour distinguer les vrais mots de contexte des skip-grams et les faux mots de contexte obtenus par échantillonnage négatif. Vous pouvez effectuer un produit scalaire entre les inclusions de mots cibles et de contexte pour obtenir des prédictions pour les étiquettes et calculer la perte par rapport aux vraies étiquettes dans l'ensemble de données.

Modèle Word2Vec sous-classé

Utilisez l' API Keras Subclassing pour définir votre modèle Word2Vec avec les couches suivantes:

  • target_embedding : Une tf.keras.layers.Embedding couche qui recherche l'intégration d'un mot quand il apparaît comme un mot cible. Le nombre de paramètres dans cette couche sont (vocab_size * embedding_dim) .
  • context_embedding : Une autre tf.keras.layers.Embedding couche qui recherche l'intégration d'un mot quand il apparaît comme un mot de contexte. Le nombre de paramètres dans cette couche sont les mêmes que ceux target_embedding , à savoir (vocab_size * embedding_dim) .
  • dots : A tf.keras.layers.Dot couche qui calcule le produit scalaire de embeddings cibles et le contexte d'une paire d'entraînement.
  • flatten : A tf.keras.layers.Flatten couche d'aplatir les résultats de dots couche en logits.

Avec le modèle sous - classé, vous pouvez définir l' call() fonction qui accepte (target, context) paires qui peuvent ensuite être transmises dans leur couche d' enrobage correspondant. Remodeler le context_embedding pour effectuer un produit scalaire avec target_embedding et retourner le résultat aplaties.

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

Définir la fonction de perte et compiler le modèle

Pour simplifier, vous pouvez utiliser tf.keras.losses.CategoricalCrossEntropy comme une alternative à la perte d'échantillonnage négatif. Si vous souhaitez écrire votre propre fonction de perte personnalisée, vous pouvez également le faire comme suit :

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

Il est temps de construire votre modèle ! Instanciez votre classe Word2Vec avec une dimension d'intégration de 128 (vous pouvez expérimenter avec différentes valeurs). Compiler le modèle avec la tf.keras.optimizers.Adam optimiseur.

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

Définissez également un rappel pour enregistrer les statistiques d'entraînement pour Tensorboard.

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

Former le modèle avec dataset de dataset préparé ci - dessus pour un certain nombre d'époques.

word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20
64/64 [==============================] - 1s 8ms/step - loss: 1.6081 - accuracy: 0.2307
Epoch 2/20
64/64 [==============================] - 0s 2ms/step - loss: 1.5883 - accuracy: 0.5536
Epoch 3/20
64/64 [==============================] - 0s 2ms/step - loss: 1.5394 - accuracy: 0.5982
Epoch 4/20
64/64 [==============================] - 0s 2ms/step - loss: 1.4555 - accuracy: 0.5719
Epoch 5/20
64/64 [==============================] - 0s 2ms/step - loss: 1.3573 - accuracy: 0.5771
Epoch 6/20
64/64 [==============================] - 0s 2ms/step - loss: 1.2613 - accuracy: 0.6035
Epoch 7/20
64/64 [==============================] - 0s 2ms/step - loss: 1.1719 - accuracy: 0.6383
Epoch 8/20
64/64 [==============================] - 0s 2ms/step - loss: 1.0891 - accuracy: 0.6716
Epoch 9/20
64/64 [==============================] - 0s 2ms/step - loss: 1.0121 - accuracy: 0.7041
Epoch 10/20
64/64 [==============================] - 0s 2ms/step - loss: 0.9405 - accuracy: 0.7334
Epoch 11/20
64/64 [==============================] - 0s 2ms/step - loss: 0.8740 - accuracy: 0.7600
Epoch 12/20
64/64 [==============================] - 0s 2ms/step - loss: 0.8125 - accuracy: 0.7837
Epoch 13/20
64/64 [==============================] - 0s 2ms/step - loss: 0.7558 - accuracy: 0.8038
Epoch 14/20
64/64 [==============================] - 0s 2ms/step - loss: 0.7036 - accuracy: 0.8207
Epoch 15/20
64/64 [==============================] - 0s 2ms/step - loss: 0.6558 - accuracy: 0.8360
Epoch 16/20
64/64 [==============================] - 0s 2ms/step - loss: 0.6121 - accuracy: 0.8496
Epoch 17/20
64/64 [==============================] - 0s 2ms/step - loss: 0.5721 - accuracy: 0.8618
Epoch 18/20
64/64 [==============================] - 0s 2ms/step - loss: 0.5357 - accuracy: 0.8738
Epoch 19/20
64/64 [==============================] - 0s 2ms/step - loss: 0.5026 - accuracy: 0.8836
Epoch 20/20
64/64 [==============================] - 0s 2ms/step - loss: 0.4723 - accuracy: 0.8925
<keras.callbacks.History at 0x7f022ce1d390>

Tensorboard affiche désormais la précision et la perte du modèle Word2Vec.

%tensorboard --logdir logs

Recherche et analyse intégrées

Obtenir en utilisant les coefficients de pondération à partir du modèle get_layer() et get_weights() . Le get_vocabulary() fonction fournit le vocabulaire pour construire un fichier de métadonnées avec un jeton par ligne.

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

Créez et enregistrez les vecteurs et le fichier de métadonnées.

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

Télécharger le vectors.tsv et metadata.tsv pour analyser les incorporations obtenus dans le Embedding projecteur .

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

Prochaines étapes

Ce tutoriel vous a montré comment implémenter un modèle Word2Vec skip-gram avec un échantillonnage négatif à partir de zéro et visualiser les plongements de mots obtenus.