Path: blob/master/site/ja/tutorials/text/word2vec.ipynb
25118 views
Copyright 2020 The TensorFlow Authors.
word2vec
word2vec は単一のアルゴリズムではなく、大規模なデータセットから単語の埋め込みを学習するために使用できるモデルアーキテクチャと最適化のファミリです。word2vec により学習された埋め込みは、さまざまなダウンストリームの自然言語処理タスクで成功することが証明されています。
注意: このチュートリアルは、ベクトル空間での単語表現の効率的な推定と単語とフレーズの分散表現とその構成に基づいていますが、論文の正確な実装ではなく、重要なアイデアを説明することを目的としています。
これらの論文では、単語の表現を学習するための 2 つの方法が提案されています。
連続バッグオブワードモデルでは、周囲のコンテキストワードに基づいて中間の単語を予測します。コンテキストは、与えられた (中間) 単語の前後のいくつかの単語で構成されます。このアーキテクチャでは、コンテキスト内の単語の順序が重要ではないため、バッグオブワードモデルと呼ばれます。
連続スキップグラムモデルは、同じ文の与えられた単語の前後の特定の範囲内の単語を予測します。この例を以下に示します。
このチュートリアルでは、スキップグラムアプローチを使用します。最初に、説明のために 1 つの文を使用して、スキップグラムとその他の概念について説明します。次に、小さなデータセットで独自の word2vec モデルをトレーニングします。このチュートリアルには、トレーニング済みの埋め込みをエクスポートして TensorFlow Embedding Projector で可視化するためのコードも含まれています。
スキップグラムとネガティブサンプリング
バッグオブワードモデルは、与えられたコンテキスト (前後の単語) から単語を予測しますが、スキップグラムモデルは、与えられた単語自体から単語のコンテキスト (前後の単語) を予測します。モデルは、トークンをスキップできる n-gram であるスキップグラムでトレーニングされます (例については、下の図を参照してください)。単語のコンテキストは、context_word
が target_word
の前後のコンテキストに現れる (target_word, context_word)
の一連のスキップグラムペアによって表すことができます。
次の 8 つの単語の文を考えてみましょう。
The wide road shimmered in the hot sun.
この文の 8 つの単語のそれぞれのコンテキストワードは、ウィンドウサイズによって定義されます。ウィンドウサイズは、context word
と見なすことができる target_word
の前後の単語の範囲を指定します。以下は、さまざまなウィンドウサイズに基づくターゲットワードのスキップグラムの表です。
注意: このチュートリアルでは、ウィンドウサイズ n
は、前後に n 個の単語があり、合計ウィンドウ 範囲が 2*n+1 個の単語であるということを意味します。
スキップグラムモデルのトレーニングの目的は、与えられたターゲットワードからコンテキストワードを予測する確率を最大化することです。一連の単語 w1、w2、... wT の場合、目的は平均対数確率として記述できます。
ここで、c
はトレーニングコンテキストのサイズです。基本的なスキップグラムの定式化では、ソフトマックス関数を使用してこの確率を定義します。
ここで、v と v' は単語のターゲットとコンテキストのベクトル表現であり、W 語彙サイズです。
この定式化の分母を計算するには、語彙全体に対して完全なソフトマックスを実行する必要があります。これは、多くの場合、大きな項 (105-107) です。
ノイズコントラスト推定 (NCE) 損失関数は、完全なソフトマックスの効率的な近似値です。単語の分布をモデル化するのではなく、単語の埋め込みを学習することを目的として、NCE 損失を単純化してネガティブサンプリングを使用することができます。
ターゲットワードの単純化されたネガティブサンプリングの目的は、コンテキストワードをノイズ分布 Pn(w) ワードから抽出された num_ns
のネガティブサンプルから区別することです。より正確には、語彙全体の完全なソフトマックスの効率的な近似は、スキップグラムペアの場合、コンテキストワードと num_ns
ネガティブサンプル間の分類問題としてターゲットワードの損失を提示します。
ネガティブサンプルは、context_word
が target_word
の window_size
の前後に現れないように、(target_word, context_word)
ペアとして定義されます。この例の文の場合、以下はいくつかの潜在的なネガティブサンプルです (window_size
が 2
の場合)。
次のセクションでは、1 つの文に対してスキップグラムとネガティブサンプルを生成します。また、サブサンプリング手法についても学習し、チュートリアルの後半でポジティブトレーニングとネガティブトレーニングサンプルの分類モデルをトレーニングします。
セットアップ
例文をベクトル化する
次の文を考えてみましょう。
The wide road shimmered in the hot sun.
文をトークン化します。
トークンから整数インデックスへのマッピングを保存する語彙を作成します。
整数インデックスからトークンへのマッピングを保存する逆語彙を作成します。
文をベクトル化します。
1 つの文からスキップグラムを生成する
tf.keras.preprocessing.sequence
モジュールは、word2vec のデータ準備を簡素化する便利な関数を提供します。 tf.keras.preprocessing.sequence.skipgrams
を使用して、範囲 [0, vocab_size)
のトークンから指定された window_size
で example_sequence
からスキップグラムペアを生成します。
注意: negative_samples
は、ここでは 0
に設定されています。これは、この関数によって生成されたネガティブサンプルのバッチ処理にコードが少し必要だからです。次のセクションでは、別の関数を使用してネガティブサンプリングを実行します。
いくつかのポジティブのスキップグラムを出力します。
1 つのスキップグラムのネガティブサンプリング
skipgrams
関数は、指定されたウィンドウスパンをスライドすることにより、すべてのポジティブのスキップグラムのペアを返します。トレーニング用のネガティブサンプルとして機能する追加のスキップグラムのペアを生成するには、語彙からランダムな単語をサンプリングする必要があります。tf.random.log_uniform_candidate_sampler
関数を使用して、ウィンドウ内の特定のターゲットワードに対して num_ns
のネガティブサンプルをサンプリングします。1 つのスキップグラムのターゲットワードで関数を呼び出し、コンテキストワードを真のクラスとして渡して、サンプリングから除外できます。
重要点: [5, 20]
範囲の num_ns
(ポジティブなコンテキストワードあたりのネガティブサンプルの数)は、小規模なデータセットで機能することが示されています。[2, 5]
範囲の num_ns
は、より大きなデータセットの場合に十分です。
1 つのトレーニングサンプルを作成する
与えられたポジティブの (target_word, context_word)
スキップグラムに対して、target_word
のウィンドウ サイズの前後に現れない num_ns
のネガティブサンプルのコンテキストワードもあります。1
のポジティブの context_word
と num_ns
のネガティブのコンテキストワードを 1 つのテンソルにバッチ処理します。これにより、ターゲットワードごとにポジティブのスキップグラム (1
とラベル付ける) とネガティブのサンプル (0
とラベル付ける) のセットが生成されます。
上記のスキップグラムの例から、ターゲットワードのコンテキストと対応するラベルを確認してください。
(target, context, label)
テンソルのタプルは、スキップグラム ネガティブサンプリング word2vec モデルをトレーニングするための 1 つのトレーニングサンプルを構成します。ターゲットの形状は (1,)
であるのに対し、コンテキストとラベルの形状は (1+num_ns,)
であることに注意してください。
まとめ
この図は、文からトレーニングサンプルを生成する手順をまとめたものです。
temperature
と code
という単語は、入力文の一部ではないことに注意してください。これらは、上の図で使用されている他の特定のインデックスと同様の語彙に属しています。
すべてのステップを 1 つの関数にコンパイルする
スキップグラム サンプリングテーブル
大規模なデータセットでは語彙が多くなり、ストップワードなどのより頻繁に使用される単語の数も多くなります。一般的に出現する単語 (the
、is
、on
など) のサンプリングから得られたトレーニングサンプルは、モデルの学習に役立つ情報をあまり提供しません。Mikolov et al. は、埋め込みの品質を改善するための有用な方法として、頻繁に使用される単語のサブサンプリングを提案しています。
tf.keras.preprocessing.sequence.skipgrams
関数は、任意のトークンをサンプリングする確率をエンコードするためのサンプリングテーブル引数を受け入れます。tf.keras.preprocessing.sequence.make_sampling_table
を使用して、単語頻度ランクに基づく確率的サンプリングテーブルを生成し、それを skipgrams
関数に渡します。vocab_size
が 10 の場合のサンプリング確率を調べます。
sampling_table[i]
は、データセットで i 番目に最も一般的な単語をサンプリングする確率を示します。この関数は、サンプリングの単語頻度の Zipf 分布を想定しています。
重要点: tf.random.log_uniform_candidate_sampler
は、語彙頻度が対数一様 (Zipf の) 分布に従うことを既に想定しています。これらの分布加重サンプリングを使用すると、ネガティブのサンプリング目標をトレーニングするための単純な損失関数を使用して、Noise Contrastive Estimation (NCE) 損失を概算するのにも役立ちます。
トレーニングデータを生成する
上記のすべての手順を、任意のテキストデータセットから取得したベクトル化された文のリストに対して呼び出せる関数にコンパイルします。スキップグラムの単語ペアをサンプリングする前に、サンプリングテーブルが作成されることに注意してください。この関数は後のセクションで使用します。
word2vec のトレーニングデータを準備する
スキップグラム ネガティブ サンプリング ベースの word2vec モデルで 1 つの文を処理する方法を理解することにより、より大きな文のリストからトレーニングサンプルを生成できます。
テキストコーパスをダウンロードする
このチュートリアルでは、シェイクスピア著作のテキストファイルを使用します。次の行を変更して、このコードを独自のデータで実行します。
ファイルからテキストを読み取り、最初の数行を出力します。
空でない行を使用して、次の手順として tf.data.TextLineDataset
オブジェクトを作成します。
コーパスから文をベクトル化する
TextVectorization
レイヤーを使用して、コーパスから文をベクトル化します。このレイヤの使用について詳しくは、テキスト分類のチュートリアルを参照してください。上記の最初の数文から、テキストは大文字または小文字にする必要があり、句読点を削除する必要があることに注意してください。これを行うには、TextVectorization レイヤーで使用する custom_standardization function
を定義します。
テキストデータセットで TextVectorization.adapt
を呼び出して語彙を作成します。
レイヤーの状態がテキストコーパスを表すように調整されると、TextVectorization.get_vocabulary
を使用して語彙にアクセスできます。この関数は、頻度によって (降順で) 並べ替えられたすべての語彙トークンのリストを返します。
vectorize_layer
を使用して、text_ds
(tf.data.Dataset
) 内の各要素のベクトルを生成できるようになりました。Dataset.batch
、Dataset.prefetch
、Dataset.map
、Dataset.unbatch
を適用します。
データセットから配列を取得する
これで、整数でエンコードされた文の tf.data.Dataset
ができました。word2vec モデルをトレーニングするためのデータセットを準備するには、データセットを文ベクトル シーケンスのリストにフラット化します。この手順は、データセット内の各文を繰り返し処理してポジティブなサンプルとネガティブなサンプルを生成するために必要です。
注意: 前に定義した generate_training_data()
は TensorFlow 以外の Python/NumPy 関数を使用するため、tf.data.Dataset.map
で tf.py_function
や tf.numpy_function
を使用することもできます。
sequences
からいくつかのサンプルを調べます。
シーケンスからトレーニングサンプルを生成する
sequences
は、int でエンコードされた文のリストになりました。前に定義した generate_training_data
関数を呼び出すだけで、word2vec モデルのトレーニングサンプルを生成できます。要約すると、関数は各シーケンスの各単語を反復処理して、ポジティブおよびネガティブなコンテキストワードを収集します。ターゲット、コンテキスト、およびラベルの長さは同じであり、トレーニングサンプルの総数を表す必要があります。
データセットを構成してパフォーマンスを改善する
潜在的に多数のトレーニングサンプルに対して効率的なバッチ処理を実行するには、tf.data.Dataset
API を使用します。このステップの後、word2vec モデルをトレーニングするための (target_word, context_word), (label)
要素の tf.data.Dataset
オブジェクトが作成されます。
Dataset.cache
と Dataset.prefetch
を適用してパフォーマンスを向上させます。
モデルとトレーニング
word2vec モデルは、スキップグラムからの真のコンテキストワードと、ネガティブサンプリングによって取得された偽のコンテキストワードを区別する分類器として実装できます。ターゲットワードとコンテキストワードの埋め込みの間で内積乗算を実行して、ラベルの予測を取得し、データセット内の真のラベルに対する損失関数を計算できます。
サブクラス化された word2vec モデル
Keras Subclassing API を使用して、次のレイヤーで word2vec モデルを定義します。
target_embedding
:tf.keras.layers.Embedding
レイヤーは単語がターゲットワードとして表示されたときにその単語の埋め込みを検索します。このレイヤーのパラメータ数は(vocab_size * embedded_dim)
です。context_embedding
: これはもう一つのtf.keras.layers.Embedding
レイヤーで単語がコンテキストワードとして表示されたときに、その単語の埋め込みを検索します。このレイヤーのパラメータ数は、target_embedding
のパラメータ数と同じです。つまり、(vocab_size * embedded_dim)
です。dots
: これはトレーニングペアからターゲットとコンテキストの埋め込みの内積を計算するtf.keras.layers.Dot
レイヤーです。flatten
:tf.keras.layers.Flatten
レイヤーは、dots
レイヤーの結果をロジットにフラット化します。
サブクラス化されたモデルを使用すると、(target, context)
ペアを受け入れる call()
関数を定義し、対応する埋め込みレイヤーに渡すことができる context_embedding
の形状を変更して、target_embedding
で内積を実行し、フラット化された結果を返します。
重要点: target_embedding
レイヤーと context embedded
レイヤーも共有できます。また、両方の埋め込みを連結して、最終的な word2vec 埋め込みとして使用することもできます。
損失関数の定義とモデルのコンパイル
簡単にするためには、ネガティブサンプリング損失の代わりに tf.keras.losses.CategoricalCrossEntropy
を使用できます。独自のカスタム損失関数を記述する場合は、次のようにします。
モデルを構築します。128 の埋め込み次元で word2vec クラスをインスタンス化します (さまざまな値を試してみてください)。モデルを tf.keras.optimizers.Adam
オプティマイザーでコンパイルします。
また、TensorBoard のトレーニング統計をログに記録するコールバックを定義します。
いくつかのエポックで、dataset
でモデルをトレーニングします。
TensorBoard は、word2vec モデルの精度と損失を表示します。
埋め込みのルックアップと分析
Model.get_layer
と Layer.get_weights
を使用して、モデルから重みを取得します。TextVectorization.get_vocabulary
関数は、1 行に 1 つのトークンでメタデータファイルを作成するための語彙を提供します。
ベクトルとメタデータファイルを作成して保存します。
vectors.tsv
と metadata.tsv
をダウンロードして、取得した埋め込みを埋め込みプロジェクタで分析します。
次のステップ
このチュートリアルでは、ゼロからネガティブサンプリングを使用してスキップグラムの word2vec モデルを実装し、取得した単語の埋め込みを視覚化する方法を実演しました。
単語ベクトルとその数学的表現についての詳細は、こちらを参照してください。
高度なテキスト処理についての詳細は、言語理解のための Transformer モデルチュートリアルを参照してください。
事前トレーニング済みの埋め込みモデルに興味がある場合は、TF-Hub CORD-19 Swivel Embeddings の探索や多言語ユニバーサルセンテンス エンコーダーも参照してください。
また、新しいデータセットでモデルをトレーニングすることもできます(TensorFlow データセットには多くのデータセットがあります)。