TensorFlowで事前トレーニング済みの単語埋め込み(word2vecまたはGlove)を使用する


95

最近、畳み込みテキスト分類の興味深い実装を確認しました。ただし、私が確認したすべてのTensorFlowコードは、次のようなランダムな(事前トレーニングされていない)埋め込みベクトルを使用しています。

with tf.device('/cpu:0'), tf.name_scope("embedding"):
    W = tf.Variable(
        tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
        name="W")
    self.embedded_chars = tf.nn.embedding_lookup(W, self.input_x)
    self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)

誰かがランダムなものの代わりにWord2vecまたはGloVeの事前訓練された単語の埋め込みの結果を使用する方法を知っていますか?

回答:


130

TensorFlowで事前トレーニング済みの埋め込みを使用する方法はいくつかあります。レッツは、あなたが呼ばれるnumpyの配列の埋め込みを持っていると言うことembeddingで、vocab_size行とembedding_dim列と、あなたはテンソル作成したいWの呼び出しで使用することができますtf.nn.embedding_lookup()

  1. 単に作成するWようtf.constant()かかることembedding、その値として:

    W = tf.constant(embedding, name="W")

    これは最も簡単な方法ですが、aの値はtf.constant()メモリに複数回保存されるため、メモリ効率が良くありません。以来embedding非常に大きくなることが、あなただけのおもちゃの例については、このアプローチを使用する必要があります。

  2. Wとして作成tf.Variableし、NumPy配列からtf.placeholder()

    W = tf.Variable(tf.constant(0.0, shape=[vocab_size, embedding_dim]),
                    trainable=False, name="W")
    
    embedding_placeholder = tf.placeholder(tf.float32, [vocab_size, embedding_dim])
    embedding_init = W.assign(embedding_placeholder)
    
    # ...
    sess = tf.Session()
    
    sess.run(embedding_init, feed_dict={embedding_placeholder: embedding})

    これによりembedding、グラフにのコピーが保存されなくなりますが、行列の2つのコピーを一度にメモリに保持するのに十分なメモリが必要になります(NumPy配列用とNumPy配列用tf.Variable)。トレーニング中に埋め込み行列を一定に保持することを想定しているため、Wで作成されてtrainable=Falseいることに注意してください。

  3. 埋め込みが別のTensorFlowモデルの一部としてトレーニングされた場合、を使用しtf.train.Saverて、他のモデルのチェックポイントファイルから値をロードできます。これは、埋め込み行列がPythonを完全にバイパスできることを意味します。Wオプション2のように作成し、次の手順を実行します。

    W = tf.Variable(...)
    
    embedding_saver = tf.train.Saver({"name_of_variable_in_other_model": W})
    
    # ...
    sess = tf.Session()
    embedding_saver.restore(sess, "checkpoint_filename.ckpt")

次のようにWを作成します。W= np.loadtxt( "/ media / w2vTest.txt"、dtype = 'string'、delimiter = '')これは行として作成されます:['in' '0.070312 ...... '-0.0625']。ここに問題があります!'in'を削除し、数値を文字列からfloat32に変換した後、これを私のWと見なす必要がありますか?これが当てはまる場合、「in」をそれぞれのベクトルに接続するにはどうすればよいですか?または、数字をfloat32に変換してから、そのままにしておく必要があります。tensorflowが必要なすべての処理を行うことを期待していますか?ありがとう!
user3147590

4
ああ、ここにはいくつかのオプションがあります。TensorFlow演算を使用してテキストファイルをテンソルに変換することもできますtf.decode_csv()が、これにはコストがかかる可能性があります(特に、Tensor列ごとに1 つ作成し、数値を連結する必要があります)。おそらく、より簡単な代替策は、NumPy配列として入力を使用pandas.read_csv()pandas.DataFrame.as_matrix()て取得することです。
mrry 2016

3
NumPy配列は、returnの呼び出し後にガベージコレクションする必要がありsess.run(embedding_init, ...)ます(プログラムへの参照を保持しない場合)。プログラムの構造によっては、配列を解放するdel embeddingembeddingNumPy配列はどこにあるか)必要があります。
mrry

1
@mrry:オプション1について、具体的には「tf.constant()の値がメモリに複数回格納されるため、メモリ効率が良くない」と言えますか?GPUまたはCPUのメモリは非効率ですか?より一般的には、tf.constant()がメモリ内に複数のコピーを持たなければならないのに、オプション2のtf.Variable()+フィードプレースホルダーにこの問題がないのはなぜですか?
Gabriel Parent、

1
あなたも「tf.constantの値は、()、メモリ内で複数回保存されている」なぜだろう場合は、この答えを見てみましょう:stackoverflow.com/a/42450418/5841473
alyaxey

33

このメソッドを使用して、埋め込みをロードおよび共有します。

W = tf.get_variable(name="W", shape=embedding.shape, initializer=tf.constant_initializer(embedding), trainable=False)

埋め込みはnumpy行列の列または行にする必要がありますか?
Greyshack 2018

6

@mrryの答えは正しくありません。これは、ネットワークが実行されるたびに埋め込みの重みの上書きを促すため、ミニバッチアプローチに従ってネットワークをトレーニングすると、埋め込みの重みが上書きされます。したがって、私の見解では、事前トレーニング済み埋め込みの正しい方法は次のとおりです。

embeddings = tf.get_variable("embeddings", shape=[dim1, dim2], initializer=tf.constant_initializer(np.array(embeddings_matrix))

LiuJiaの回答の完全な複製。
TimZaman 16

4
@TimZaman ..実際、彼はtrainable = False引数を欠いているため、その過程で埋め込みを微調整することになります。
Shatu

4
また、Eugenioの推論は正しくないと思います。すべてのミニバッチで "embedding_init"オペレーションを実行する必要はありません。すべてうまくいきます。つまり、トレーニングの開始時に一度だけ埋め込み初期化を実行します。
Shatu

@Shatu埋め込みの初期化がトレーニングの開始時にのみ実行されるようにするにはどうすればよいですか?

1
@ dust0x ..埋め込みのサイズが十分に小さい場合は、初期値として指定できます。それらが非常に大きい場合は、すべての変数の初期化子を実行するときに、それらをfeed_dictで渡すことができます。十分に明確でない場合はお知らせください。両方のアプローチのサンプルコードを投稿します。
Shatu

6

2.0互換性のある回答:Googleが開発し、オープンソース化された、事前トレーニング済みの埋め込みが多数あります。

それらのいくつかは Universal Sentence Encoder (USE), ELMO, BERT、などです。コードでそれらを再利用するのは非常に簡単です。

再利用するためのコードはPre-Trained EmbeddingUniversal Sentence Encoder以下に示します。

  !pip install "tensorflow_hub>=0.6.0"
  !pip install "tensorflow>=2.0.0"

  import tensorflow as tf
  import tensorflow_hub as hub

  module_url = "https://tfhub.dev/google/universal-sentence-encoder/4"
  embed = hub.KerasLayer(module_url)
  embeddings = embed(["A long sentence.", "single-word",
                      "http://example.com"])
  print(embeddings.shape)  #(3,128)

Googleが開発し、オープンソース化した事前トレーニング済みの埋め込みの詳細については、TF Hub Linkを参照してください。


5

tensorflowバージョン2では、埋め込みレイヤーを使用すると非常に簡単です

X=tf.keras.layers.Embedding(input_dim=vocab_size,
                            output_dim=300,
                            input_length=Length_of_input_sequences,
                            embeddings_initializer=matrix_of_pretrained_weights
                            )(ur_inp)

3

私も埋め込みの問題に直面していたので、データセットを使用して詳細なチュートリアルを書きました。ここで私が試したものを追加したいと思いますこの方法を試すこともできます、

import tensorflow as tf

tf.reset_default_graph()

input_x=tf.placeholder(tf.int32,shape=[None,None])

#you have to edit shape according to your embedding size


Word_embedding = tf.get_variable(name="W", shape=[400000,100], initializer=tf.constant_initializer(np.array(word_embedding)), trainable=False)
embedding_loopup= tf.nn.embedding_lookup(Word_embedding,input_x)

with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for ii in final_:
            print(sess.run(embedding_loopup,feed_dict={input_x:[ii]}))

ここでは、チュートリアルのIpythonの詳細なを使用しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.