0 和 1 之间的余弦相似度

Bra*_*roy 7 python similarity cosine-similarity gensim scikit-learn

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

在信息检索的情况下,两个文档的余弦相似度将在 0 到 1 的范围内,因为术语频率(使用 tf-idf 权重)不能为负。两个词频向量之间的夹角不能大于 90°。

特殊之处在于我希望计算来自两个不同 word2vec 模型的两个向量之间的相似性。但是,这些模型已经对齐,因此它们实际上应该在相同的向量空间中表示它们的单词。我可以像这样计算单词 inmodel_a和单词 in之间的相似度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)
Run Code Online (Sandbox Code Playgroud)

但是sim是 [-1,1] 范围内的相似性度量。是否有科学合理的方法将其映射到 [0,1] 范围?直觉上我会认为像

norm_sim = (sim + 1) / 2
Run Code Online (Sandbox Code Playgroud)

没关系,但我不确定这对于余弦相似度的实际含义是否是好的做法。如果没有,是否建议使用其他相似性指标?

我试图让值介于 0 和 1 之间的原因是因为数据将传输给一位同事,该同事将使用它作为她的机器学习系统的特征,该系统期望所有值都在 0 和 1 之间。她的直觉是取绝对值,但在我看来,这是一个更糟糕的选择,因为这样你就可以将对立面映射为相同。不过,考虑到余弦相似度的实际含义,我可能是错的。因此,如果采用绝对值是一种好方法,我们也可以这样做。

goj*_*omo 6

您有充分的理由选择 0.0-1.0(尽管许多学习算法应该在 -1.0 到 1.0 的范围内表现良好)。如果您的唯一目的是获得 0.0-1.0 的范围,那么您的norm_sim 重新缩放 -1.0 到 1.0 到 0.0 到 1.0 就可以了……但当然结果值不再是真正的余弦相似度。

\n\n

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

\n\n

使用无符号绝对值将是一个坏主意,因为它会改变相似性 \xe2\x80\x93 的排名顺序,从而将一些“本机”最不相似的结果向上移动。

\n\n

人们已经在限制词向量的维度上仅具有非负值方面进行了工作,通常的好处是所得到的维度更有可能是单独可解释的。(例如参见https://cs.cmu.edu/~bmurphy/NNSE/。)但是,gensim 不支持此变体,并且只有尝试它才能揭示它是否对任何特定项目更好。

\n\n

此外,还有其他研究表明,通常的词向量可能不会在原点周围“平衡”(因此您会看到比随机超球面中的点预期的负余弦相似性要少),并且使它们变得更加平衡通常会改善它们执行其他任务的能力。看: https://arxiv.org/abs/1702.01417v2

\n