如何计算两个张量之间的余弦相似度?

20

我有两个标准化张量,需要使用TensorFlow计算这些张量之间的余弦相似度。如何实现?

cosine(normalize_a,normalize_b)

    a = tf.placeholder(tf.float32, shape=[None], name="input_placeholder_a")
    b = tf.placeholder(tf.float32, shape=[None], name="input_placeholder_b")
    normalize_a = tf.nn.l2_normalize(a,0)        
    normalize_b = tf.nn.l2_normalize(b,0)
4个回答

31

这将完成工作:

a = tf.placeholder(tf.float32, shape=[None], name="input_placeholder_a")
b = tf.placeholder(tf.float32, shape=[None], name="input_placeholder_b")
normalize_a = tf.nn.l2_normalize(a,0)        
normalize_b = tf.nn.l2_normalize(b,0)
cos_similarity=tf.reduce_sum(tf.multiply(normalize_a,normalize_b))
sess=tf.Session()
cos_sim=sess.run(cos_similarity,feed_dict={a:[1,2,3],b:[2,4,6]})

这将打印0.99999988


非常感谢您的回答。余弦相似度公式是否通过首先对输入进行归一化来简化?您的公式似乎比维基百科上的公式 https://en.wikipedia.org/wiki/Cosine_similarity 要简单。 - Matias
3
如果你不先做标准化,那么在计算向量内积 a*b 后,你需要除以向量 a 和 b 的范数的乘积。但如果你提前标准化,就不需要这么做了。这是因为标准化后,a=normalize_a=a/||a||(b同理)。 - Miriam Farber
为什么不使用matmul? - Euler_Salter
1
tf.matmul() 是矩阵乘法,tf.multiply() 是逐元素相乘。 - gizzmole

25

时代在变化。通过调用tf.losses.cosine_distance,可以使用最新的TF API进行计算。

示例:

import tensorflow as tf
import numpy as np


x = tf.constant(np.random.uniform(-1, 1, 10)) 
y = tf.constant(np.random.uniform(-1, 1, 10))
s = tf.losses.cosine_distance(tf.nn.l2_normalize(x, 0), tf.nn.l2_normalize(y, 0), dim=0)
print(tf.Session().run(s))

当然,1 - s就是余弦相似度!


为什么1-s是余弦相似度? - Euler_Salter
4
因为 s 是余弦距离,而不是相似度。 - Rajarshee Mitra
1
1-s不需要。该函数被称为距离,但返回相似度。我认为这是因为它在tf.losses中。看一下代码,我可能错了。第274行。losses = 1 - math_ops.reduce_sum(radial_diffs, axis=(dim,), keep_dims=True) https://github.com/tensorflow/tensorflow/blob/r1.4/tensorflow/python/ops/losses/losses_impl.py - patrick.ryan93
2
@RajarsheeMitra 这个能用于整个矩阵吗?也就是说,假设每一行都是与向量v相同维度的向量,计算向量v与矩阵中所有行之间的余弦距离? - ajaanbaahu
@ajaanbaahu 是的。 - Rajarshee Mitra
@patrick.ryan93 需要1-s。math_ops.reduce_sum(radial_diffs, axis=(dim,), keep_dims=True)是余弦相似度。 - dragonfly

2

ab之间的余弦相似度:

tf.keras.losses.CosineSimilarity()(a, b)

2
提示:这个收敛到-1.0,因为它被设计成作为一个损失函数使用。如果你想要一个收敛到1.0的东西,可以使用tf.keras.metrics.CosineSimilarity代替。 - Jakub Kukul

1
您可以像这样对向量或矩阵进行归一化:

[batch_size*hidden_num]
states_norm=tf.nn.l2_normalize(states,dim=1)
[batch_size * embedding_dims]
embedding_norm=tf.nn.l2_normalize(embedding,dim=1)
#assert hidden_num == embbeding_dims
after mat [batch_size*embedding]
user_app_scores = tf.matmul(states_norm,embedding_norm,transpose_b=True)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接