このページは Cloud Translation API によって翻訳されました。
Switch to English

Word2Vec

TensorFlow.orgで表示 GoogleColabで実行 GitHubでソースを表示ノートブックをダウンロード

Word2Vecは単一のアルゴリズムではなく、大規模なデータセットから単語の埋め込みを学習するために使用できるモデルアーキテクチャと最適化のファミリです。 Word2Vecを通じて学習した埋め込みは、さまざまなダウンストリームの自然言語処理タスクで成功することが証明されています。

これらの論文は、単語の表現を学習するための2つの方法を提案しました。

  • 周囲の文脈単語に基づいて中間単語を予測する連続Bag-of-Wordsモデル。コンテキストは、現在の(中間の)単語の前後のいくつかの単語で構成されます。このアーキテクチャは、コンテキスト内の単語の順序が重要ではないため、bag-of-wordsモデルと呼ばれます。
  • 同じ文の現在の単語の前後の特定の範囲内の単語を予測する連続スキップグラムモデル。これの実際の例を以下に示します。

このチュートリアルでは、スキップグラムアプローチを使用します。最初に、説明のために1つの文を使用して、スキップグラムやその他の概念について説明します。次に、小さなデータセットで独自のWord2Vecモデルをトレーニングします。このチュートリアルには、トレーニング済みの埋め込みをエクスポートし、 TensorFlow埋め込みプロジェクターで視覚化するためのコードも含まれています。

スキップグラムとネガティブサンプリング

バッグオブワードモデルは隣接するコンテキストが与えられた単語を予測しますが、スキップグラムモデルは単語自体が与えられた場合に単語のコンテキスト(または隣接するもの)を予測します。モデルはスキップグラムでトレーニングされます。スキップグラムは、トークンをスキップできるようにするnグラムです(例については、下の図を参照してください)。単語のコンテキストは、スキップグラムペアのセットを表すことができる(target_word, context_word) context_wordの隣接文脈に現れるtarget_word

次の8語の文を考えてみましょう。

広い道は暑い太陽の下できらめきました。

この文の8つの単語のそれぞれのコンテキスト単語は、ウィンドウサイズによって定義されます。ウィンドウサイズは、 context wordと見なすことができるtarget_word両側のワードのスパンを決定します。さまざまなウィンドウサイズに基づくターゲットワードのスキップグラムのこの表をご覧ください。

word2vec_skipgrams

スキップグラムモデルのトレーニングの目的は、ターゲットワードが与えられた場合にコンテキストワードを予測する可能性を最大化することです。 W 1、W 2ワードのシーケンスのため、... T wは、目的は、平均対数確率のように書くことができます。

word2vec_skipgram_objective

ここで、 cはトレーニングコンテキストのサイズです。基本的なスキップグラムの定式化は、softmax関数を使用してこの確率を定義します。

word2vec_full_softmax

ここで、 vv 'は単語のターゲットおよびコンテキストベクトル表現であり、 Wは語彙サイズです。

この定式化の分母を計算するには、多くの場合大きな(10 5 -10 7 )用語である語彙全体​​に対して完全なソフトマックスを実行する必要があります。

ノイズコントラスト推定損失関数は、完全なソフトマックスの効率的な近似です。単語の分布をモデル化する代わりに単語の埋め込みを学習することを目的として、NCE損失を単純化して、負のサンプリングを使用することができます。

ターゲットワードの単純化されたネガティブサンプリングの目的は、コンテキストワードをワードのノイズ分布P n (w)から抽出されたnum_nsネガティブサンプルから区別することです。より正確には、語彙に対する完全なソフトマックスの効率的な近似は、スキップグラムペアの場合、コンテキスト単語とnum_nsの負のサンプル間の分類問題としてターゲット単語の損失をもたらすことです。

負のサンプルは、context_wordがwindow_size近傍に表示されないように、(target_word、context_word)ペアとして定義されます。例文の場合、これらはいくつかの潜在的な負のサンプルです( window_sizeが2の場合)。

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

次のセクションでは、1つの文に対してスキップグラムとネガティブサンプルを生成します。また、チュートリアルの後半で、サブサンプリング手法について学習し、ポジティブトレーニングとネガティブトレーニングの例の分類モデルをトレーニングします。

セットアップ

pip install -q tqdm
import io
import itertools
import numpy as np
import os
import re
import string
import tensorflow as tf
import tqdm

from tensorflow.keras import Model, Sequential
from tensorflow.keras.layers import Activation, Dense, Dot, Embedding, Flatten, GlobalAveragePooling1D, Reshape
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
SEED = 42 
AUTOTUNE = tf.data.experimental.AUTOTUNE

例文をベクトル化する

次の文を考えてみましょう。
The wide road shimmered in the hot sun.

文をトークン化します。

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

トークンから整数インデックスへのマッピングを保存するための語彙を作成します。

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}

整数インデックスからトークンへのマッピングを保存するための逆語彙を作成します。

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

あなたの文をベクトル化します。

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

1つの文からスキップグラムを生成する

tf.keras.preprocessing.sequenceモジュールは、Word2Vecのデータ準備を簡素化する便利な関数を提供します。あなたは使用することができますtf.keras.preprocessing.sequence.skipgramsからスキップグラムのペアを生成するexample_sequence与えてwindow_sizeの範囲内のトークンから[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

いくつかのポジティブなスキップグラムを見てください。

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

1つのスキップグラムの負のサンプリング

skipgrams関数は、指定されたウィンドウスパン上をスライドすることにより、すべての正のスキップグラムペアを返します。トレーニングのネガティブサンプルとして機能する追加のスキップグラムペアを生成するには、語彙からランダムな単語をサンプリングする必要があります。 tf.random.log_uniform_candidate_sampler関数を使用して、ウィンドウ内の特定のターゲット単語のnum_ns個の負のサンプルをサンプリングします。 1つのスキップグラムのターゲットワードで関数を呼び出し、コンテキストワードをtrueクラスとして渡して、サンプリングから除外することができます。

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

1つのトレーニング例を作成する

与えられた正の場合(target_word, context_word)スキップグラムを、あなたは今も持っているnum_nsのウィンドウサイズの周辺に表示されない負のサンプリングされたコンテキストの言葉target_word1正のcontext_wordnum_ns負のコンテキストワードを1つのテンソルにバッチ処理します。これにより、ターゲットワードごとに一連のポジティブスキップグラム( 1とラベル付け)とネガティブサンプル( 0とラベル付け)が生成されます。

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

上記のスキップグラムの例から、ターゲットワードのコンテキストと対応するラベルを見てください。

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

(target, context, label)テンサーのタプルは、スキップグラムネガティブサンプリングWord2Vecモデルをトレーニングするための1つのトレーニング例を構成します。ターゲットは形状(1,)あり、コンテキストとラベルは形状(1+num_ns,)

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

概要

この写真は、文からトレーニング例を生成する手順をまとめたものです。

word2vec_negative_sampling

すべてのステップを1つの関数にコンパイルします

スキップグラムサンプリングテーブル

データセットが大きいということは、ストップワードなどのより頻繁な単語の数が多い、より大きな語彙を意味します。一般的にoccuring言葉サンプリングから得られたトレーニング例(のような、 the isonから学ぶためのモデルのために多くの有用な情報を追加しないでください)。 ミコロフ他埋め込み品質を向上させるための有用な方法として、頻繁な単語のサブサンプリングを提案します。

tf.keras.preprocessing.sequence.skipgrams関数は、サンプリングテーブル引数を受け入れて、任意のトークンをサンプリングする確率をエンコードします。 tf.keras.preprocessing.sequence.make_sampling_tableを使用して、単語頻度ランクベースの確率的サンプリングテーブルを生成し、それをskipgrams関数に渡すことがskipgramsます。 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]は、データセット内でi番目に一般的な単語をサンプリングする確率を示します。この関数は、サンプリング用の単語頻度のジップの分布を想定しています。

トレーニングデータを生成する

上記のすべてのステップを、任意のテキストデータセットから取得したベクトル化された文のリストで呼び出すことができる関数にコンパイルします。スキップグラムワードペアをサンプリングする前に、サンプリングテーブルが作成されていることに注意してください。この機能は後のセクションで使用します。

# 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

Word2Vecのトレーニングデータを準備する

スキップグラムネガティブサンプリングベースのWord2Vecモデルで1つの文を処理する方法を理解すると、より大きな文のリストからトレーニング例を生成することができます。

テキストコーパスをダウンロード

このチュートリアルでは、シェイクスピアの執筆のテキストファイルを使用します。次の行を変更して、このコードを自分のデータで実行します。

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

ファイルからテキストを読み、最初の数行を見てください。

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.

空でない行を使用して、次の手順のためにtf.data.TextLineDatasetオブジェクトを作成します。

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

コーパスから文をベクトル化する

TextVectorizationレイヤーを使用して、コーパスから文をベクトル化できます。このテキスト分類チュートリアルで、このレイヤーの使用について詳しく学んでください。上記の最初の数文から、テキストは1つのケースである必要があり、句読点を削除する必要があることに注意してください。これを行うには、TextVectorizationレイヤーで使用できるcustom_standardization functionを定義します。

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

テキストデータセットでadaptを呼び出して、語彙を作成します。

vectorize_layer.adapt(text_ds.batch(1024))

レイヤーの状態がテキストコーパスを表すように調整されたら、 get_vocabulary()get_vocabulary()て語彙にアクセスできます。この関数は、頻度でソート(降順)されたすべての語彙トークンのリストを返します。

# 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を使用して、 text_ds各要素のベクトルを生成できるようになりました。

def vectorize_text(text):
  text = tf.expand_dims(text, -1)
  return tf.squeeze(vectorize_layer(text))

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

データセットからシーケンスを取得します

tf.data.Datasetで、整数でエンコードされた文のtf.data.Datasetができました。 Word2Vecモデルをトレーニングするためのデータセットを準備するには、データセットを文ベクトルシーケンスのリストにフラット化します。このステップは、データセット内の各文を反復処理して正と負の例を生成するために必要です。

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

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

シーケンスからトレーニング例を生成する

sequencesは、intでエンコードされた文のリストになりました。前に定義したgenerate_training_data()関数を呼び出すだけで、Word2Vecモデルのトレーニング例が生成されます。要約すると、関数は各シーケンスの各単語を反復処理して、正と負のコンテキスト単語を収集します。ターゲットの長さ、コンテキスト、ラベルは同じである必要があり、トレーニング例の総数を表します。

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:26<00:00, 1216.33it/s]
64678 64678 64678



パフォーマンスのためにデータセットを構成する

潜在的に多数のトレーニング例に対して効率的なバッチ処理を実行するには、tf.data.Dataset使用します。このステップの後、Word2Vecモデルをトレーニングするための(target_word, context_word), (label)要素のtf.data.Datasetオブジェクトがtf.data.Datasetます。

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

cache()prefetch()を追加して、パフォーマンスを向上させます。

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

モデルとトレーニング

Word2Vecモデルは、スキップグラムからの真のコンテキストワードとネガティブサンプリングによって取得された偽のコンテキストワードを区別するための分類子として実装できます。ターゲットワードとコンテキストワードの埋め込みの間に内積を実行して、ラベルの予測を取得し、データセット内の実際のラベルに対する損失を計算できます。

サブクラス化されたWord2Vecモデル

Keras Subclassing APIを使用して、次のレイヤーでWord2Vecモデルを定義します。

  • target_embedding :ターゲット単語として表示されたときに単語の埋め込みを検索するtf.keras.layers.Embeddingレイヤー。このレイヤーのパラメーターの数は(vocab_size * embedding_dim)です。
  • context_embedding :コンテキストワードとして表示されたときにワードの埋め込みを検索する別のtf.keras.layers.Embeddingレイヤー。このレイヤーのパラメーターの数は、 target_embeddingのパラメーターの数と同じです。つまり(vocab_size * embedding_dim)です。
  • dots :トレーニングペアからのターゲットとコンテキストの埋め込みのドット積を計算するtf.keras.layers.Dotレイヤー。
  • flattendotsレイヤーの結果をtf.keras.layers.Flattenにフラット化するためのtf.keras.layers.Flattenレイヤー。

サブレーザーモデルを使用すると、 (target, context)ペアを受け入れるcall()関数を定義できます。このペアは、対応する埋め込みレイヤーに渡すことができます。 context_embedding形状を変更して、 target_embeddingを使用して内積を実行し、フラット化された結果を返します。

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
    we = self.target_embedding(target)
    ce = self.context_embedding(context)
    dots = self.dots([ce, we])
    return self.flatten(dots)

損失関数を定義し、モデルをコンパイルします

簡単にするために、負のサンプリング損失の代わりにtf.keras.losses.CategoricalCrossEntropyを使用できます。独自のカスタム損失関数を作成する場合は、次のようにすることもできます。

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

モデルを作成する時が来ました! 128の埋め込みディメンションを使用してWord2Vecクラスをインスタンス化します(さまざまな値を試すことができます)。 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'])

また、テンソルボードのトレーニング統計をログに記録するためのコールバックを定義します。

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

いくつかのエポックについて、上記で準備したdatasetてモデルをトレーニングします。

word2vec.fit(dataset, epochs=20, callbacks=[tensorboard_callback])
Epoch 1/20
 1/63 [..............................] - ETA: 0s - loss: 1.6095 - accuracy: 0.1836WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/summary_ops_v2.py:1277: stop (from tensorflow.python.eager.profiler) is deprecated and will be removed after 2020-07-01.
Instructions for updating:
use `tf.profiler.experimental.stop` instead.
WARNING:tensorflow:Callbacks method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0115s vs `on_train_batch_end` time: 0.0314s). Check your callbacks.
63/63 [==============================] - 0s 6ms/step - loss: 1.6083 - accuracy: 0.2314
Epoch 2/20
63/63 [==============================] - 0s 5ms/step - loss: 1.5893 - accuracy: 0.5571
Epoch 3/20
63/63 [==============================] - 0s 5ms/step - loss: 1.5427 - accuracy: 0.6123
Epoch 4/20
63/63 [==============================] - 0s 5ms/step - loss: 1.4607 - accuracy: 0.5851
Epoch 5/20
63/63 [==============================] - 0s 5ms/step - loss: 1.3626 - accuracy: 0.5880
Epoch 6/20
63/63 [==============================] - 0s 5ms/step - loss: 1.2653 - accuracy: 0.6134
Epoch 7/20
63/63 [==============================] - 0s 5ms/step - loss: 1.1742 - accuracy: 0.6454
Epoch 8/20
63/63 [==============================] - 0s 5ms/step - loss: 1.0897 - accuracy: 0.6795
Epoch 9/20
63/63 [==============================] - 0s 5ms/step - loss: 1.0113 - accuracy: 0.7118
Epoch 10/20
63/63 [==============================] - 0s 5ms/step - loss: 0.9388 - accuracy: 0.7408
Epoch 11/20
63/63 [==============================] - 0s 5ms/step - loss: 0.8717 - accuracy: 0.7664
Epoch 12/20
63/63 [==============================] - 0s 5ms/step - loss: 0.8098 - accuracy: 0.7897
Epoch 13/20
63/63 [==============================] - 0s 5ms/step - loss: 0.7528 - accuracy: 0.8079
Epoch 14/20
63/63 [==============================] - 0s 5ms/step - loss: 0.7005 - accuracy: 0.8244
Epoch 15/20
63/63 [==============================] - 0s 5ms/step - loss: 0.6527 - accuracy: 0.8391
Epoch 16/20
63/63 [==============================] - 0s 5ms/step - loss: 0.6089 - accuracy: 0.8524
Epoch 17/20
63/63 [==============================] - 0s 5ms/step - loss: 0.5690 - accuracy: 0.8644
Epoch 18/20
63/63 [==============================] - 0s 5ms/step - loss: 0.5327 - accuracy: 0.8752
Epoch 19/20
63/63 [==============================] - 0s 5ms/step - loss: 0.4996 - accuracy: 0.8852
Epoch 20/20
63/63 [==============================] - 0s 5ms/step - loss: 0.4695 - accuracy: 0.8941

<tensorflow.python.keras.callbacks.History at 0x7fc1c56345f8>

Tensorboardは、Word2Vecモデルの精度と損失を表示するようになりました。

%tensorboard --logdir logs

word2vec_tensorboard

ルックアップと分析の埋め込み

get_layer()およびget_weights()を使用して、モデルから重みを取得します。 get_vocabulary()関数は、1行に1つのトークンを持つメタデータファイルを作成するための語彙を提供します。

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

ベクターとメタデータファイルを作成して保存します。

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

vectors.tsvmetadata.tsvをダウンロードして、 EmbeddingProjectorで取得した埋め込みを分析します。

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

次のステップ

このチュートリアルでは、最初からネガティブサンプリングを使用してスキップグラムWord2Vecモデルを実装し、取得した単語の埋め込みを視覚化する方法を示しました。