python - 0 和 1 之间的余弦相似度

标签 python scikit-learn gensim similarity cosine-similarity

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

In the case of information retrieval, the cosine similarity of two documents will range from 0 to 1, since the term frequencies (using tf–idf weights) cannot be negative. The angle between two term frequency vectors cannot be greater than 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. 她的直觉是取绝对值,但在我看来,这是一个更糟糕的选择,因为这样你就把对立面映射为相同的。不过,考虑到余弦相似度的实际含义,我可能是错的。因此,如果取绝对值是好方法,我们也可以这样做。

最佳答案

您有充分的理由选择 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。)

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

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

此外,还有其他研究表明,通常的词向量可能不会围绕原点“平衡”(因此您会看到比随机超球面中的点预期的负余弦相似性要少),并且会移动它们更加平衡通常会提高他们完成其他任务的能力。请参阅:https://arxiv.org/abs/1702.01417v2

关于python - 0 和 1 之间的余弦相似度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56316903/

相关文章:

python - ChatGPT 词嵌入最相似的词

java - 安装 Eclipse Classic 4.2 时遇到问题

python - 通过管道将sample_weight参数与XGBoost结合使用

python - 比较 NumPy 数组的相似性

scikit-learn - 当 p > n 时 sklearn 如何进行线性回归?

python - 拟合 sklearn GridSearchCV 模型

python - 如何打印gensim词典和语料库

python - 在pandas中,如何收集所有行的数据并将新数据合并为一行?

python - 不在 Python 中执行的函数

python - 如何仅用另一个数组的值替换 numpy 数组的部分值?