Pomoc chronić Wielkiej Rafy Koralowej z TensorFlow na Kaggle Dołącz Wyzwanie

Word2Vec

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Word2Vec nie jest pojedynczym algorytmem, a raczej rodziną architektur modeli i optymalizacji, których można używać do uczenia się osadzania słów z dużych zbiorów danych. Osadzania wyuczone za pomocą Word2Vec okazały się skuteczne w wielu dalszych zadaniach przetwarzania języka naturalnego.

Artykuły te proponowały dwie metody uczenia się reprezentacji słów:

  • Ciągłe Bag-of-Words model, który przewiduje środkowy wyraz w oparciu o kontekst otaczający słowa. Kontekst składa się z kilku słów przed i po bieżącym (środkowym) słowie. Ta architektura nazywana jest modelem torby słów, ponieważ kolejność słów w kontekście nie jest ważna.
  • Ciągłe Skip-gram model, który przewidywania wyrazów ciągu pewnym zakresie przed i po bieżącym słowem w tym samym zdaniu. Praktyczny przykład tego jest podany poniżej.

W tym samouczku użyjesz metody pomijania gramów. Najpierw zapoznasz się z przeskokami i innymi pojęciami, używając jednego zdania do ilustracji. Następnie wytrenujesz własny model Word2Vec na małym zbiorze danych. Ten poradnik zawiera również kod do wyeksportować wyszkolonych zanurzeń i zwizualizować je w Osadzanie projektora TensorFlow .

Pomijanie gramów i negatywne próbkowanie

Podczas gdy model worka słów przewiduje słowo biorąc pod uwagę kontekst sąsiedni, model pomijania przewiduje kontekst (lub sąsiedzi) słowa, biorąc pod uwagę samo słowo. Model jest szkolony na pomijanych gramach, które są n-gramami, które umożliwiają pomijanie tokenów (przykład na poniższym diagramie). Kontekście słowo może być reprezentowana przez zestaw par pominięcia-gramowych (target_word, context_word) gdzie context_word pojawia się w sąsiednim kontekście target_word .

Rozważ następujące zdanie składające się z 8 słów.

Szeroka droga lśniła w gorącym słońcu.

Słowa kontekstu dla każdego z 8 słów tego zdania są zdefiniowane przez rozmiar okna. Rozmiar okna określa zakres słów na każdej stronie target_word , które mogą być uznane za context word . Spójrz na tę tabelę przeskoków dla słów docelowych w oparciu o różne rozmiary okien.

word2vec_skipgrams

Celem szkoleniowym modelu pomijania gramów jest maksymalizacja prawdopodobieństwa przewidywania słów kontekstowych przy danym słowie docelowym. Dla sekwencji słów w 1, w 2, ... W T, celem może być zapisany jako średnia prawdopodobieństwem dziennika

word2vec_skipgram_objective

gdzie c jest wielkość pomieszczeń treningowych. Podstawowe sformułowanie pomijania gramów definiuje to prawdopodobieństwo za pomocą funkcji softmax.

word2vec_full_softmax

w których V i V są docelowymi i kontekst wektor reprezentacje słowy, a W oznacza słowa wielkości.

Obliczeniowych mianownik tego preparatu polega na przeprowadzeniu pełnej Softmax na całych słów użytych co często jest duża (10 5 -10 7) warunkach.

Hałas Kontrastywna Oszacowanie funkcja strata jest skutecznym przybliżeniem do pełnej Softmax. Z celem, aby dowiedzieć się zanurzeń słowo zamiast modelowania rozkładu słowo, NCE strata może być uproszczone do korzystania negatywny próbkowanie.

Uproszczona ujemny próbek celem słowa celem jest odróżnić od kontekstu słowo próbki num_ns ujemnych sporządzonych z podziału szumu P N (W) słowa. Dokładniej, efektywne przybliżenie pełnej Softmax nad słownictwo jest dla pary Skip-gramowej, pozować straty za słowa docelowego jako problem klasyfikacji między słowem kontekstowego i num_ns próbek ujemnych.

Ujemne próbki określa się jako (target_word, context_word) pary, tak że context_word nie występują w window_size sąsiedztwie target_word. Dla przykładu zdanie, to kilka potencjalnych negatywnych próbek (gdy window_size jest 2).

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

W następnej sekcji wygenerujesz pominięte gramy i próbki ujemne dla pojedynczego zdania. W dalszej części samouczka dowiesz się również o technikach podpróbkowania i trenowaniu modelu klasyfikacji dla pozytywnych i negatywnych przykładów szkoleniowych.

Ustawiać

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

Wektoryzuj przykładowe zdanie

Rozważ następujące zdanie:
The wide road shimmered in the hot sun.

Tokenize zdanie:

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

Utwórz słownik, aby zapisać mapowania z tokenów na indeksy liczb całkowitych.

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}

Utwórz słownik odwrotny, aby zapisać odwzorowania z indeksów liczb całkowitych na tokeny.

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

Zwektoryzuj swoje zdanie.

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

Generuj przeskoki z jednego zdania

tf.keras.preprocessing.sequence moduł dostarcza użytecznych funkcji, które ułatwiają przygotowanie danych dla Word2Vec. Można użyć tf.keras.preprocessing.sequence.skipgrams do generowania pary pominięcia gramów z example_sequence z danym window_size od żetonów w przedziale [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

Spójrz na kilka pozytywnych przeskoków.

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)

Próbkowanie ujemne dla jednego pominięcia grama

W skipgrams zwraca wszystkie pozytywne pary pominięcia gramów przesuwając w danym przedziale okna. Aby wytworzyć dodatkowe pary pomijanych gramów, które posłużyłyby jako negatywne próbki do nauki, musisz pobrać losowe słowa ze słownika. Użyj tf.random.log_uniform_candidate_sampler funkcję do próbki num_ns liczby próbek ujemnych dla danego słowa docelowego w oknie. Możesz wywołać funkcję na słowie docelowym jednego skip-grams i przekazać słowo kontekstowe jako true class, aby wykluczyć je z próbkowania.

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

Skonstruuj jeden przykład szkolenia

Dla danego dodatniego (target_word, context_word) skip-gram, teraz również num_ns negatywne próbą słowa kontekście, że nie pojawiają się w sąsiedztwie rozmiar okna target_word . Okresowym 1 dodatnie context_word i num_ns negatywnym kontekście słowa w jednym tensora. W ten sposób powstaje zbiór pozytywnych skip-gramów (oznaczony jako 1 ) i próbek ujemnych (oznaczony jako 0 ) dla każdego słowa docelowego.

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

Przyjrzyj się kontekstowi i odpowiadającym mu etykietom słowa docelowego z powyższego przykładu pomijania gramatycznego.

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]

Krotką (target, context, label) tensorów stanowi jeden przykład szkolenia dla treningu Skip-Gram-ujemnych próbek modelu Word2Vec. Należy zauważyć, że cel ma kształt (1,) , podczas gdy kontekst i etykiety są w kształcie (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)

Streszczenie

Ten obrazek podsumowuje procedurę generowania przykładu treningowego ze zdania.

word2vec_negative_sampling

Skompiluj wszystkie kroki w jedną funkcję

Pomiń tabelę próbkowania

Duży zbiór danych oznacza większe słownictwo z większą liczbą częstszych słów, takich jak stopwords. Przykłady szkoleniowe otrzymane z próbek powszechnie występujące słowa (takie jak , the is , on ) nie dodać wiele przydatnych informacji dla modelu do nauki. Mikołow i in. zasugeruj podpróbkowanie częstych słów jako pomocną praktykę poprawiającą jakość osadzania.

tf.keras.preprocessing.sequence.skipgrams funkcja przyjmuje argumentu tabeli próbkowania do prawdopodobieństw kodowanie próbek dowolny znacznik. Można użyć tf.keras.preprocessing.sequence.make_sampling_table wygenerować tabelę probabilistyczny próbkowania Ranking słowo częstotliwości w oparciu i przekazać go do skipgrams funkcji. Spójrz na prawdopodobieństw próbkowania dla vocab_size 10.

sampling_table = tf.keras.preprocessing.sequence.make_sampling_table(size=10)
print(sampling_table)
[0.00315225 0.00315225 0.00547597 0.00741556 0.00912817 0.01068435
 0.01212381 0.01347162 0.01474487 0.0159558 ]

sampling_table[i] oznacza prawdopodobieństwo próbkowania i-najczęstszych słowa w zbiorze danych. Funkcja zakłada dystrybucję Zipf jest z częstotliwościami próbkowania na słowo.

Generuj dane treningowe

Skompiluj wszystkie opisane powyżej kroki w funkcję, którą można wywołać na liście zwektoryzowanych zdań uzyskanych z dowolnego zestawu danych tekstowych. Zauważ, że tabela próbkowania jest tworzona przed próbkowaniem par słów pomijanych-gramów. Użyjesz tej funkcji w dalszych rozdziałach.

# 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

Przygotuj dane treningowe dla Word2Vec

Rozumiejąc, jak pracować z jednym zdaniem w modelu Word2Vec opartym na próbkowaniu ujemnym, możesz przystąpić do generowania przykładów szkoleniowych z większej listy zdań!

Pobierz korpus tekstowy

W tym samouczku użyjesz pliku tekstowego z tekstami Szekspira. Zmień następujący wiersz, aby uruchomić ten kod na własnych danych.

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

Przeczytaj tekst z pliku i spójrz na kilka pierwszych linijek.

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.

Używać bez pustej linii skonstruować tf.data.TextLineDataset obiektu dla następnych etapów.

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

Wektoryzuj zdania z korpusu

Można użyć TextVectorization warstwę wektorować zdań z korpusu. Więcej informacji na temat korzystania z tej warstwy w tej klasyfikacji Tekst tutoriala. Zauważ z kilku pierwszych zdań powyżej, że tekst musi być w jednym przypadku, a interpunkcja musi zostać usunięta. W tym celu zdefiniowania custom_standardization function , które mogą być używane w warstwie 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)

Zadzwoń do adapt na zbiorze tekstowym stworzyć słownictwo.

vectorize_layer.adapt(text_ds.batch(1024))

Gdy stan warstwy został przystosowany do reprezentowania korpus, słownictwo uzyskać można get_vocabulary() . Ta funkcja zwraca listę wszystkich tokenów słownika posortowanych (malejąco) według ich częstotliwości.

# 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 może teraz być użyty do generowania wektorów do każdego elementu text_ds .

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

Uzyskaj sekwencje ze zbioru danych

Teraz mają tf.data.Dataset z całkowitych kodowane zdań. Aby przygotować zestaw danych do uczenia modelu Word2Vec, spłaszcz zestaw danych do listy sekwencji wektorów zdań. Ten krok jest wymagany, ponieważ powtarzasz każde zdanie w zestawie danych, aby uzyskać pozytywne i negatywne przykłady.

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

Spójrz na kilka przykładów z 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', '', '', '', '', '', '', '', '']

Generuj przykłady treningowe z sekwencji

sequences jest teraz lista int kodowane zdań. Wystarczy zadzwonić pod generate_training_data() funkcję zdefiniowaną wcześniej wygenerować przykłady szkoleniowe dla modelu Word2Vec. Podsumowując, funkcja iteruje po każdym słowie z każdej sekwencji, aby zebrać pozytywne i negatywne słowa kontekstu. Długość celu, konteksty i etykiety powinny być takie same, reprezentując całkowitą liczbę przykładów szkoleniowych.

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)

Skonfiguruj zbiór danych pod kątem wydajności

Aby wykonać efektywne dozowanie na potencjalnie dużą liczbę przykładów treningowych, użyj tf.data.Dataset API. Po tym etapie, to masz tf.data.Dataset przedmiot (target_word, context_word), (label) elementów wytresować modelu 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)>

Dodaj cache() i prefetch() w celu zwiększenia wydajności.

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

Model i szkolenie

Model Word2Vec może być zaimplementowany jako klasyfikator w celu rozróżnienia między słowami prawdziwego kontekstu a pominiętymi słowami i słowami fałszywego kontekstu uzyskanymi przez próbkowanie ujemne. Możesz wykonać iloczyn skalarny między osadzonymi słowami docelowymi i kontekstowymi, aby uzyskać prognozy dla etykiet i straty obliczeniowe względem prawdziwych etykiet w zestawie danych.

Podklasy Model Word2Vec

Użyj API Keras instacji zdefiniować swój model Word2Vec z następujących warstw:

  • target_embedding : a tf.keras.layers.Embedding warstwa, która patrzy na osadzanie słowem, gdy pojawia się jako słowo docelowej. Liczba parametrów tej warstwy jest (vocab_size * embedding_dim) .
  • context_embedding : Kolejny tf.keras.layers.Embedding warstwa, która patrzy na osadzanie słowem, gdy pojawia się jako słowo kontekstowego. Liczba parametrów tej warstwy są takie same jak te w target_embedding , czyli (vocab_size * embedding_dim) .
  • dots : A tf.keras.layers.Dot warstwa oblicza się iloczyn skalarny docelowych i kontekst zanurzeń z pary treningowej.
  • flatten : a tf.keras.layers.Flatten warstwa spłaszczenia wyniki dots warstwową logits.

Z podklasy modelu można określić call() funkcję akceptuje (target, context) pary, która może być następnie przekazane w odpowiednie warstwy wstawiania. Przekształcenia context_embedding wykonać iloczyn skalarny z target_embedding i powrót spłaszczone wynik.

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

Zdefiniuj funkcję straty i skompiluj model

Dla uproszczenia można korzystać tf.keras.losses.CategoricalCrossEntropy jako alternatywa dla ujemnego utraty próbkowania. Jeśli chcesz napisać własną niestandardową funkcję straty, możesz to również zrobić w następujący sposób:

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

Czas zbudować swój model! Utwórz wystąpienie klasy Word2Vec z wymiarem osadzania równym 128 (możesz poeksperymentować z różnymi wartościami). Skompilować model z tf.keras.optimizers.Adam optymalizatora.

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

Zdefiniuj również wywołanie zwrotne, aby rejestrować statystyki treningowe dla Tensorboard.

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

Trenować model z dataset przygotowany powyżej pewnej liczby epok.

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 pokazuje teraz dokładność i stratę modelu Word2Vec.

%tensorboard --logdir logs

Wyszukiwanie i analiza osadzania

Uzyskania wagi z modelu za pomocą get_layer() i get_weights() . get_vocabulary() funkcja zapewnia słownictwa, aby zbudować plik metadanych z jednego żetonu na linię.

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

Utwórz i zapisz wektory i plik metadanych.

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

Pobierz vectors.tsv i metadata.tsv przeanalizować uzyskane zanurzeń w projektorze Osadzanie .

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

Następne kroki

Ten samouczek pokazał, jak zaimplementować od podstaw model Word2Vec pomijania gramatycznego z negatywnym próbkowaniem i wizualizować uzyskane osadzania słów.