web-dev-qa-db-ja.com

TensorFlowで事前学習済みのWord埋め込み(Word2vecまたはGlove)を使用する

畳み込みテキスト分類 の興味深い実装を最近レビューしました。ただし、私がレビューしたすべての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の事前トレーニング済みのWord埋め込みの結果を使用する方法を知っている人はいますか?

86
user3147590

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

  1. 単にWtf.constant() として作成し、その値としてembeddingを取ります:

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

    これは最も簡単な方法ですが、tf.constant()の値がメモリに複数回保存されるため、メモリ効率がよくありません。 embeddingは非常に大きくなる可能性があるため、この方法はおもちゃの例にのみ使用してください。

  2. Wtf.Variableとして作成し、 tf.placeholder() を介してNumPy配列から初期化します。

    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つのコピーを一度にメモリに保持するのに十分なメモリが必要です(1つはNumPy配列用、もう1つはtf.Variable用)。トレーニング中に埋め込み行列定数を保持することを前提としていることに注意してください。したがって、Wtrainable=Falseで作成されます。

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

    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")
    
124
mrry

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

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

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

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

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

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 example 最初から理解したい場合は、見てください。

2
Aaditya Ura