Réserve cette date! Google I / O revient du 18 au 20 mai S'inscrire maintenant
Cette page a été traduite par l'API Cloud Translation.
Switch to English

Word2Vec

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

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

Ces articles proposent deux méthodes pour apprendre les représentations des mots:

  • Modèle de sac de mots continu qui prédit le mot du milieu en fonction des mots contextuels environnants. Le contexte se compose de quelques mots avant et après le mot courant (du milieu). Cette architecture s'appelle un modèle de sac de mots car l'ordre des mots dans le contexte n'est pas important.
  • Modèle de saut-gramme continu qui prédisent les mots dans une certaine plage avant et après le mot actuel dans la même phrase. Un exemple concret de ceci est donné ci-dessous.

Vous utiliserez l'approche skip-gramme dans ce didacticiel. Tout d'abord, vous explorerez les skip-grammes et d'autres concepts en utilisant une seule phrase à titre d'illustration. Ensuite, vous allez entraîner votre propre modèle Word2Vec sur un petit ensemble de données. Ce didacticiel contient également du code pour exporter les incorporations entraînées et les visualiser dans le projecteur d'incorporation TensorFlow .

Échantillonnage par sauts de gramme et négatif

Alors qu'un modèle de sac de mots prédit un mot étant donné le contexte voisin, un modèle skip-gram prédit le contexte (ou les voisins) d'un mot, étant donné le mot lui-même. Le modèle est entraîné sur les skip-grammes, 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-gramme 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 plage de mots de chaque côté d'un target_word qui peut être considéré comme un context word . Jetez un œil à ce tableau de sauts-grammes 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 des mots de contexte étant donné le mot cible. Pour une suite de mots w 1 , w 2 , ... w T , l'objectif peut être écrit comme la probabilité logarithmique moyenne

word2vec_skipgram_objective

c est la taille du contexte de formation. La formulation skip-gram de base définit cette probabilité en utilisant la fonction softmax.

word2vec_full_softmax

v et v ' sont des représentations vectorielles cibles et contextuelles des mots et W est la taille du vocabulaire.

Le calcul du dénominateur de cette formulation consiste à effectuer un softmax complet sur l'ensemble des mots de vocabulaire qui est souvent de grands termes (10 5 -10 7 ).

La fonction de perte d' estimation de contraste de bruit est une approximation efficace pour un softmax complet. Dans le but d'apprendre les incorporations de mots au lieu de modéliser la distribution des mots, la perte de NCE peut être simplifiée pour utiliser un échantillonnage négatif.

L'objectif d'échantillonnage négatif simplifié pour un mot cible est de distinguer le mot de contexte de num_ns échantillons négatifs tirés de la distribution de bruit P n (w) des mots. Plus précisément, une approximation efficace du softmax complet sur le vocabulaire consiste, pour une paire skip-gramme, à 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 une paire (target_word, context_word) de telle sorte que le context_word n'apparaisse pas dans le voisinage window_size du target_word. Pour la phrase d'exemple, ce sont quelques échantillons négatifs potentiels (lorsque window_size vaut 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 entraînerez un modèle de classification pour des exemples de formation positifs et négatifs plus loin dans le didacticiel.

Installer

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

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

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 des jetons aux 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 vers des 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-grammes à partir d'une phrase

Le module tf.keras.preprocessing.sequence fournit des fonctions utiles qui simplifient la préparation des données pour Word2Vec. Vous pouvez utiliser tf.keras.preprocessing.sequence.skipgrams pour générer des paires skip-gramme à partir de example_sequence avec une window_size donnée à window_size de jetons dans la plage [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 skip-grammes positifs.

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

Échantillonnage négatif pour un skip-gramme

La fonction skipgrams renvoie toutes les paires skip-gram positives en glissant sur une étendue de fenêtre donnée. Pour produire des paires de sauts-grammes supplémentaires qui serviraient d'échantillons négatifs pour la formation, vous devez échantillonner des mots aléatoires du vocabulaire. Utilisez la fonction tf.random.log_uniform_candidate_sampler pour échantillonner num_ns nombre d'échantillons négatifs pour un mot cible donné dans une fenêtre. Vous pouvez appeler la fonction sur un mot cible de skip-grammes 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']

Construisez un exemple de formation

Pour un skip-gramme positif donné (target_word, context_word) , vous avez maintenant également num_ns mots de contexte échantillonnés négatifs qui n'apparaissent pas dans le voisinage de taille de fenêtre de target_word . context_word les 1 mots de contexte positifs et num_ns mots de contexte négatifs en un seul tenseur. Cela produit un ensemble d'échantillons de sauts positifs (étiquetés comme 1 ) et négatifs (étiquetés comme 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 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    : 6
target_word     : hot
context_indices : [1 2 1 4 3]
context_words   : ['the', 'wide', 'the', 'shimmered', 'road']
label           : [1 0 0 0 0]

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

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

Résumé

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

word2vec_negative_sampling

Compilez toutes les étapes en une seule fonction

Tableau d'échantillonnage Skip-gram

Un grand ensemble de données signifie un vocabulaire plus large 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 coll. suggérer le sous-échantillonnage des mots fréquents comme pratique utile pour améliorer la qualité de l'incorporation.

La fonction tf.keras.preprocessing.sequence.skipgrams accepte un argument de table d'échantillonnage pour coder les probabilités d'échantillonnage de n'importe quel jeton. Vous pouvez utiliser tf.keras.preprocessing.sequence.make_sampling_table pour générer une table d'échantillonnage probabiliste basée sur le rang de fréquence des mots et la transmettre à la fonction skipgrams . Jetez un œil aux probabilités d'échantillonnage pour 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] indique la probabilité d'échantillonner le i-ème mot le plus courant dans un ensemble de données. La fonction suppose une distribution Zipf des fréquences de mot 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 texte. Notez que la table d'échantillonnage est construite avant l'échantillonnage des paires de mots sauts-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 skip-gram, vous pouvez continuer à 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

Lisez le texte du fichier et regardez 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 objet tf.data.TextLineDataset 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 le calque TextVectorization pour vectoriser les phrases du corpus. En savoir plus sur l'utilisation de cette couche dans ce didacticiel sur la classification de texte . Notez dans 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éfinissez une custom_standardization function qui peut être utilisée 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 = TextVectorization(
    standardize=custom_standardization,
    max_tokens=vocab_size,
    output_mode='int',
    output_sequence_length=sequence_length)

Appelez adapt sur l'ensemble de données texte pour créer du 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 texte, 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 du 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 untf.data.Dataset de phrases encodées en nombres entiers. 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 de vecteurs de phrases. Cette étape est nécessaire, car vous itérez sur 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 œil à 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 de formation à partir de séquences

sequences est maintenant une liste de phrases encodées en int. Appelez simplement la fonction generate_training_data() définie précédemment pour générer des exemples d'entraînement 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 identiques, 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)
print(len(targets), len(contexts), len(labels))
100%|██████████| 32777/32777 [00:30<00:00, 1085.04it/s]
65023 65023 65023

Configurer l'ensemble de données pour les performances

Pour effectuer un traitement par lots efficace pour le nombre potentiellement important d'exemples d'entraînement, utilisez l'APItf.data.Dataset . Après cette étape, vous auriez un objettf.data.Dataset d'éléments (target_word, context_word), (label) pour entraîner 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, 1)), (1024, 5)), types: ((tf.int32, tf.int64), tf.int64)>

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

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

Modèle et formation

Le modèle Word2Vec peut être implémenté en tant que classificateur pour faire la distinction entre les vrais mots de contexte de skip-grammes et les faux mots de contexte obtenus par échantillonnage négatif. Vous pouvez effectuer un produit scalaire entre les imbrications de mots cible 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 de sous -classification Keras pour définir votre modèle Word2Vec avec les couches suivantes:

  • target_embedding : un calque tf.keras.layers.Embedding qui recherche l'incorporation d'un mot lorsqu'il apparaît comme mot cible. Le nombre de paramètres de cette couche est (vocab_size * embedding_dim) .
  • context_embedding : Un autre calque tf.keras.layers.Embedding qui recherche l'incorporation d'un mot lorsqu'il apparaît en tant que mot de contexte. Le nombre de paramètres de cette couche est le même que celui de target_embedding , c'est-à-dire (vocab_size * embedding_dim) .
  • dots : Une couche tf.keras.layers.Dot qui calcule le produit scalaire des plongements de cible et de contexte à partir 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 la fonction call() qui accepte (target, context) paires (target, context) qui peuvent ensuite être passées dans leur couche d'incorporation correspondante. context_embedding le context_embedding pour exécuter un produit target_embedding avec target_embedding et renvoyer le résultat aplati.

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

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

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

Pour plus de simplicité, vous pouvez utiliser tf.keras.losses.CategoricalCrossEntropy comme alternative à la perte d'échantillonnage négative. 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'incorporation de 128 (vous pouvez expérimenter avec différentes valeurs). Compilez le modèle avec l'optimiseur 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'])

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

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

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

word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20
63/63 [==============================] - 2s 8ms/step - loss: 1.6089 - accuracy: 0.2172
Epoch 2/20
63/63 [==============================] - 0s 6ms/step - loss: 1.5924 - accuracy: 0.5918
Epoch 3/20
63/63 [==============================] - 0s 6ms/step - loss: 1.5537 - accuracy: 0.6396
Epoch 4/20
63/63 [==============================] - 0s 6ms/step - loss: 1.4771 - accuracy: 0.5907
Epoch 5/20
63/63 [==============================] - 0s 6ms/step - loss: 1.3793 - accuracy: 0.5837
Epoch 6/20
63/63 [==============================] - 0s 6ms/step - loss: 1.2807 - accuracy: 0.6060
Epoch 7/20
63/63 [==============================] - 0s 6ms/step - loss: 1.1882 - accuracy: 0.6391
Epoch 8/20
63/63 [==============================] - 0s 6ms/step - loss: 1.1023 - accuracy: 0.6738
Epoch 9/20
63/63 [==============================] - 0s 6ms/step - loss: 1.0224 - accuracy: 0.7061
Epoch 10/20
63/63 [==============================] - 0s 6ms/step - loss: 0.9481 - accuracy: 0.7355
Epoch 11/20
63/63 [==============================] - 0s 6ms/step - loss: 0.8792 - accuracy: 0.7618
Epoch 12/20
63/63 [==============================] - 0s 6ms/step - loss: 0.8157 - accuracy: 0.7862
Epoch 13/20
63/63 [==============================] - 0s 6ms/step - loss: 0.7572 - accuracy: 0.8068
Epoch 14/20
63/63 [==============================] - 0s 6ms/step - loss: 0.7036 - accuracy: 0.8240
Epoch 15/20
63/63 [==============================] - 0s 6ms/step - loss: 0.6546 - accuracy: 0.8406
Epoch 16/20
63/63 [==============================] - 0s 6ms/step - loss: 0.6099 - accuracy: 0.8548
Epoch 17/20
63/63 [==============================] - 0s 6ms/step - loss: 0.5692 - accuracy: 0.8668
Epoch 18/20
63/63 [==============================] - 0s 6ms/step - loss: 0.5323 - accuracy: 0.8781
Epoch 19/20
63/63 [==============================] - 0s 6ms/step - loss: 0.4986 - accuracy: 0.8877
Epoch 20/20
63/63 [==============================] - 0s 6ms/step - loss: 0.4681 - accuracy: 0.8966
<tensorflow.python.keras.callbacks.History at 0x7f8a3061f828>

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

%tensorboard --logdir logs

Intégration de la recherche et de l'analyse

Obtenez les poids du modèle en utilisant get_layer() et get_weights() . La fonction get_vocabulary() 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échargez les vectors.tsv et metadata.tsv pour analyser les incorporations obtenues dans le projecteur d'intégration .

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

Prochaines étapes

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