首页 > 解决方案 > 0 和 1 之间的余弦相似度

问题描述

我对计算向量之间的相似度很感兴趣,但是这种相似度必须是 0 到 1 之间的数字。关于 tf-idf 和余弦相似度的问题很多,都表明该值介于 0 和 1 之间。来自维基百科

在信息检索的情况下,两个文档的余弦相似度范围为 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 之间。她的直觉是取绝对值,但在我看来,这似乎是一个更糟糕的选择,因为这样你就会将对立面映射为相同的。不过,考虑到余弦相似度的实际含义,我可能是错的。因此,如果采用绝对值是好的方法,我们也可以这样做。

标签: pythonscikit-learngensimsimilaritycosine-similarity

解决方案


你有充分的理由更喜欢 0.0-1.0(尽管许多学习算法在 -1.0 到 1.0 的范围内应该可以做得很好)。如果您的唯一目的是获得 0.0-1.0 范围,那么您将 norm_sim 重新调整为 -1.0 到 1.0 到 0.0 到 1.0 就可以了……但当然,结果值不再是真正的余弦相似度。

这些值不再是真正的全范围角度并不一定重要。(如果算法需要真实角度,它可以使用 -1.0 到 1.0。)

使用无符号绝对值将是一个坏主意,因为它会改变相似性的排名顺序——将一些“天然”最不相似的结果向上移动。

已经有工作限制词向量在维度中只有非负值,通常的好处是结果维度更可能是单独解释的。(参见例如https://cs.cmu.edu/~bmurphy/NNSE/。)但是,gensim 不支持此变体,只有尝试它才能揭示它是否对任何特定项目更好。

此外,还有其他研究表明,通常的词向量在原点周围可能不是“平衡”的(所以你会看到比随机超球面中的点预期的负余弦相似性更少),并且将它们转移到更多平衡通常会改善他们的其他任务。见:https ://arxiv.org/abs/1702.01417v2


推荐阅读