日付を保存! Google I / Oが5月18日から20日に戻ってきます今すぐ登録
このページは Cloud Translation API によって翻訳されました。
Switch to English

Word2Vec

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

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

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

  • 周囲の文脈単語に基づいて中間単語を予測する連続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つの文のスキップグラムとネガティブサンプルを生成します。また、チュートリアルの後半で、サブサンプリング手法について学習し、ポジティブトレーニングとネガティブトレーニングの例の分類モデルをトレーニングします。

セットアップ

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

例文をベクトル化する

次の文を考えてみましょう。
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]})")
(6, 1): (hot, the)
(4, 3): (shimmered, road)
(5, 3): (in, road)
(2, 4): (wide, shimmered)
(7, 1): (sun, the)

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    : 6
target_word     : hot
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("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)

概要

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

word2vec_negative_sampling

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

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

データセットが大きいということは、語彙が多く、ストップワードなどの頻度の高い単語の数が多いことを意味します。一般的に出現する単語のサンプリングから得られたトレーニング例(のような、 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番目に一般的な単語をサンプリングする確率を示します。この関数は、サンプリング用の単語頻度のZipfの分布を想定しています。

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

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

# 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を定義します。

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

テキストデータセットで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各要素のベクトルを生成できるようになりました。

# 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:30<00:00, 1085.04it/s]
65023 65023 65023

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

潜在的に多数のトレーニング例に対して効率的なバッチ処理を実行するには、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
    word_emb = self.target_embedding(target)
    context_emb = self.context_embedding(context)
    dots = self.dots([context_emb, word_emb])
    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
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は、Word2Vecモデルの精度と損失を表示するようになりました。

%tensorboard --logdir logs

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

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:
  pass

次のステップ

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