看起来sklearn的cosine_similarity
函数有时会输出略大于1的值。这个问题已经报告并在scikit-learn(scikit-learn/scikit-learn#18122)内部讨论。这导致了在这个仓库上提交的一些问题报告(例如,#1137、#1418和#1319),建议使用默认距离函数的绝对值作为解决方法。
根据他们在scikit-learn问题中可能采取的方向,我提议对默认距离函数进行轻微的更改,以将余弦相似度函数的输出裁剪到预期的范围-1到1,从而消除这个问题,并可能防止更多问题被报告。
if distance_function is None:
distance_function = lambda x: 1 - cosine_similarity(x)
将变为
if distance_function is None:
distance_function = lambda x: 1 - np.clip(cosine_similarity(x), -1, 1)
我知道如果scikit-learn/scikit-learn#18122固定了,就不再需要这个解决方法,我们可以自己提供自定义的距离函数。因此,我完全理解如果现在认为添加这个解决方法不是必要的,但我仍然想提出这个建议,至少听取一下大家对这个方法的看法。如果这是大家所期望的,我很乐意创建PR。
我对余弦相似度的理解是,除了浮点数舍入误差之外,没有理由让值超出-1到1的范围,所以在裁剪输出时不会有行为风险。这是正确的吗?
谢谢!
1条答案
按热度按时间kpbpu0081#
感谢详细的描述!这确实是一个棘手的问题,我希望在scikit-learn中能得到解决。
我对余弦相似度的理解是,除了浮点数舍入误差之外,值不应该超出-1到1的范围,因此在截断输出时不会出现行为问题。这是正确的吗?
有一件事让我有些犹豫,那就是即使它们超出了范围,分布可能仍然具有意义。例如,在您提到的问题中,我看到一个用户的相似度测量值为1.1。如果另一个相似度测量值为1.05,那么截断这两个值将使它们具有相同的值。如果底层的错误意味着1.1和1.05的实际值是分布,并且1.1表示高于1.05的分数,那么截断将删除这些信息。
由于得到1.1的值相当高(如果它仅仅是一个舍入误差),所以我不确定问题出在哪里,这使我不太愿意默认截断它。