【发布时间】:2019-08-22 16:51:51
【问题描述】:
我对计算向量之间的相似度很感兴趣,但是这个相似度必须是0到1之间的数字。关于tf-idf和余弦相似度的问题很多,都表明该值在0到1之间。来自@ 987654321@:
在信息检索的情况下,两个的余弦相似度 文档的范围从 0 到 1,因为术语频率(使用 tf–idf 权重)不能为负。两个术语之间的角度 频率向量不能大于 90°。
特殊之处在于我希望从两个不同的 word2vec 模型中计算两个向量之间的相似度。但是,这些模型已经对齐,因此它们实际上应该在相同的向量空间中表示它们的单词。我可以像这样计算model_a 中的单词和model_b 中的单词之间的相似度
import gensim as gs
from sklearn.metrics.pairwise import cosine_similarity
model_a = gs.models.KeyedVectors.load_word2vec_format(model_a_path, binary=False)
model_b = gs.models.KeyedVectors.load_word2vec_format(model_b_path, binary=False)
vector_a = model_a[word_a].reshape(1, -1)
vector_b = model_b[word_b].reshape(1, -1)
sim = cosine_similarity(vector_a, vector_b).item(0)
但是sim 是 [-1,1] 范围内的相似性度量。是否有一种科学合理的方法可以将其映射到 [0,1] 范围?直觉上我会认为像
norm_sim = (sim + 1) / 2
没关系,但我不确定这对于余弦相似度的实际含义是否是一种好习惯。如果没有,是否建议使用其他相似性指标?
我试图让值介于 0 和 1 之间的原因是因为数据将被传输给一位同事,该同事将把它用作她的机器学习系统的一项功能,该系统期望所有值都在 0 之间和 1. 她的直觉是取绝对值,但在我看来,这似乎是一个更糟糕的选择,因为这样你就会将对立面映射为相同的。不过,考虑到余弦相似度的实际含义,我可能是错的。因此,如果采用绝对值是好的方法,我们也可以这样做。
【问题讨论】:
-
他们所说的只是一个具有标准化(单位)向量长度的向量点积。这只是两个向量之间角度的余弦(同样,如果将长度缩放为 1)。这就是 90 度参考的来源,因为超过 90 度它会变成负值。
-
为什么需要值在 0 到 1 的范围内? (像 word2vec 这样的“密集”嵌入的向量与原点的方向非常接近,因此余弦相似度可能为负。在词袋字数上,纯 TF-IDF 的结果只会是 0 到 1。)如果您的唯一目的是获得 0.0-1.0 范围,那么您的
norm_sim将 -1.0 重新缩放到 1.0 到 0.0 到 1.0 就可以了……当然,结果值不再是真正的余弦相似度。这有关系吗?不清楚你的其他目标和想要 0.0-1.0 分数的原因,但可能不是。 -
感谢您对@gojomo 的关注。我添加了最后一段来解释为什么我需要在那个范围内的这个值。如果有一种方法可以强制 word2vec 只产生正向量,那会很酷——尽管考虑到 word2vec 的语义,我不确定这可能如何工作。
-
好的,这是选择 0.0-1.0 的合理理由(尽管许多学习算法在 -1.0 到 1.0 的范围内应该可以正常工作)。这些值不再是真正的全范围角度并不一定重要。 (如果算法需要真实角度,它可以使用 -1.0 到 1.0。)使用绝对值不是一个好主意,因为它会改变相似性的排名顺序——移动一些“本机”最不相似的结果向上。
-
一直在努力限制词向量在维度中只有非负值,通常的好处是生成的维度更有可能是单独解释的。 (例如参见cs.cmu.edu/~bmurphy/NNSE/.)但是,gensim 不支持此变体,只有尝试它才能揭示它是否更适合任何特定项目。
标签: python scikit-learn gensim similarity cosine-similarity