【问题标题】:Using a pre-trained word embedding (word2vec or Glove) in TensorFlow在 TensorFlow 中使用预训练的词嵌入(word2vec 或 Glove)
【发布时间】:2016-06-11 18:59:26
【问题描述】:

我最近查看了convolutional text classification 的一个有趣的实现。然而,我查看过的所有 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 预训练词嵌入的结果而不是随机的吗?

【问题讨论】:

    标签: python numpy tensorflow deep-learning


    【解决方案1】:

    使用 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)
    
    

    【讨论】:

      【解决方案2】:

      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

      【讨论】:

        【解决方案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 example如果你想从头开始理解,看看。

        【讨论】:

          【解决方案4】:

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

          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)。请注意,我假设您希望在训练期间保持嵌入矩阵不变,因此 W 是使用 trainable=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")
            

          【讨论】:

          • 我按如下方式创建 W:W = np.loadtxt("/media/w2vTest.txt",dtype ='string',delimiter = ' ') 创建为一行:['in' '0.070312......'-0.0625']。这里有问题!在删除'in'并将数字从字符串转换为float32之后,我应该将其视为我的W吗?如果是这种情况,那么如何将“in”连接到其各自的向量?或者我需要将数字转换为 float32,然后保持原样;期望 tensorflow 将完成所有必需的处理?谢谢!
          • 啊,你有几个选择。您可以使用 TensorFlow tf.decode_csv() 操作将文本文件转换为张量,但这可能会很昂贵(特别是,它需要您为每列创建一个 Tensor,然后将数字的一起)。也许更简单的替代方法是使用 pandas.read_csv()pandas.DataFrame.as_matrix() 将输入作为 NumPy 数组。
          • NumPy 数组应该在对sess.run(embedding_init, ...) 的调用返回后进行垃圾回收(假设您没有在程序中保留对它的引用)。根据程序的结构,您可能希望del embedding(其中embedding 是 NumPy 数组)提前释放数组。
          • @mrry:你能多谈谈选项 1,更具体地说“它不是内存效率的,因为 tf.constant() 的值多次存储在内存中”。 GPU或CPU的内存效率低下?更一般的,为什么tf.constant()在内存中要多份,而选项2的tf.Variable()+feeding占位符就没有这个问题?
          • 如果您还想知道为什么“tf.constant() 的值会在内存中多次存储”,请查看以下答案:stackoverflow.com/a/42450418/5841473
          【解决方案5】:

          我使用这种方法来加载和共享嵌入。

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

          【讨论】:

          • 嵌入应该是numpy矩阵中的列还是行?
          【解决方案6】:

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

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

          【讨论】:

          • 刘佳的回答一模一样。
          • @TimZaman .. 事实上,他缺少 trainable=False 参数,因此最终会在此过程中微调他的嵌入。
          • 另外,我认为 Eugenio 的推理是不正确的。您只是不必对每个小批量运行“embedding_init”操作,一切都会好起来的。也就是说,只在训练开始时运行一次嵌入初始化。
          • @Shatu 如何确保嵌入初始化仅在训练开始时运行?
          • @dust0x .. 如果嵌入的大小足够小,您可以将它们指定为初始值。如果它们很大,您可以在为所有变量运行初始化程序时将它们传递到 feed_dict 中。如果还不够清楚,请告诉我,我会尝试为这两种方法发布一些示例代码。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-06-20
          • 2019-02-07
          • 2020-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多