在TensorFlow中使用预先训练的词嵌入(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预先训练的单词嵌入的结果而不是随机的?

几种方法可以在 TensorFlow 中使用预先训练的嵌入。假设您在一个名为 embedding 的 NumPy 数组中嵌入了 ,其中包含 vocab_size 行和 embedding_dim 列,并且您想创建一个可用于调用tf.nn.embedding_lookup()的张量W

  1. 只需将W创建为以embedding为价值的tf.constant()

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

    这是最简单的方法,但它的内存效率不高,因为tf.constant()的值在内存中多次存储。由于embedding可能非常大,因此应仅将此方法用于玩具示例。

  2. W创建为tf.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的副本,但它确实需要足够的内存来同时在内存中保留矩阵的两个副本(一个用于 NumPy 数组,一个用于tf.Variable)。请注意,我假设您希望在训练期间保持嵌入矩阵不变,因此使用 trainable=False 创建W

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

我使用此方法加载和共享嵌入。

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

兼容 2.0 答案:有许多预训练嵌入,由谷歌开发,并且是开源的。

其中一些是Universal Sentence Encoder (USE), ELMO, BERT 等,在代码中重用它们非常容易。

重用Pre-Trained Embedding的代码, Universal 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 链接。

@mrry的答案是不对的,因为它会引发对每个网络运行的嵌入权重的覆盖,因此如果您遵循小批量方法来训练您的网络,那么您正在覆盖嵌入的权重。因此,在我看来,预训练嵌入的正确方法是:

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

使用张量流版本 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)
我也

面临嵌入问题,所以我用数据集写了详细的教程。在这里我想补充一下我尝试过的你也可以试试这个方法,

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示例,如果你想从头开始了解,看看。

最新更新