在TensorFlow嵌入中有效地找到最接近的单词

Lea*_*the 10 distance embedding tensorflow

最近,我一直试图找到最接近嵌入的词.这两种最显着的方法是通过余弦距离或欧氏距离.

我试图找到如何有效地计算张量形状的余弦距离 [batch_size x embedding_size]

一种方法是解压缩张量并计算余弦距离

  #embedding is shape [vocab_size x embedding size]
  array_list = tf.unpack(batch_array)
  word_class_list = tf.unpack(embedding)
  index_list_of_closest_word = []
  for eacharray in array_list:
    list_of_distances = []
    for eachwordclass in word_class_list:
      list_of_distances.append(cosine_distance(eacharray, eachwordclass))
    index_list_of_closest_word.append(tf.argmax(tf.pack(list_of_distances)))
Run Code Online (Sandbox Code Playgroud)

但是,这种方法非常低效.是否有更有效的方式来做到这一点?我知道word2vec做得非常快,并且具有gpu功能的te​​nsorflow应该能够并行执行这些批量计算.

谢谢!

Oli*_*rot 32

余弦相似性公式是:
余弦相似度


您拥有的输入是:

  • embedding:嵌入矩阵,形状 [vocab_size, embedding_size]
  • batch_array:一组嵌入,您想要找到最接近的单词形状 [batch_size, embedding_size]
embedding = tf.placeholder(tf.float32, [vocab_size, embedding_size])
batch_array = tf.placeholder(tf.float32, [batch_size, embedding_size])
Run Code Online (Sandbox Code Playgroud)

要计算余弦相似度,您可以先对两个输入进行标准化:(
您可能希望存储标准嵌入,因为您要重复使用它)

normed_embedding = tf.nn.l2_normalize(embedding, dim=1)
normed_array = tf.nn.l2_normalize(batch_array, dim=1)
Run Code Online (Sandbox Code Playgroud)

然后你必须计算所有单词的点积(vocab_size总计)与批次中的所有数组(batch_size总计):

cosine_similarity = tf.matmul(normed_array, tf.transpose(normed_embedding, [1, 0]))
Run Code Online (Sandbox Code Playgroud)

您最终可以计算批次中每个元素的argmax:

closest_words = tf.argmax(cosine_similarity, 1)  # shape [batch_size], type int64
Run Code Online (Sandbox Code Playgroud)

  • 要找到最相似的 top-k,您还可以执行以下操作:`closest_k_words = tf.nn.top_k(cosine_similarity,k=10)` (2认同)