是否可以使用类似于1 – 余弦相似度的形式来使用scikit learn的KNeighborsClassifier?
这个回答说不行,但在KNeighborsClassifier的文档中提到,DistanceMetrics中提到的度量是可用的。距离度量中没有明确的余弦距离,可能是因为它并不是真正的距离,但据说可以将一个函数输入到度量中。我尝试将scikit learn的线性核函数输入到KNeighborsClassifier中,但它提示错误,说该函数需要两个数组作为参数。还有其他人尝试过吗?
回答:
余弦相似度通常定义为xT y / (||x|| * ||y||),如果它们相同则输出1,如果完全不同则趋向于-1。这个定义在技术上不是一个度量,因此你不能用它来使用加速结构如球树和kd树。如果你强制scikit learn使用暴力方法,你应该可以通过传递你自己的自定义距离度量对象来使用它作为距离。如果你想使用球树,可以将余弦相似度转换为有效的距离度量方法(你可以在JSAT库中找到一个)。
请注意,xT y / (||x|| * ||y||) = (x/||x||)T (y/||y||)。欧几里得距离可以等价地写成sqrt(xTx + yTy − 2 xTy)。如果我们在将数据点输入到KNeighborsClassifier之前对其进行归一化,那么对于所有x
,x^T x = 1
。因此,欧几里得距离将退化为sqrt(2 − 2x^T y)
。对于完全相同的输入,我们会得到sqrt(2-2*1) = 0
,对于完全相反的输入,我们会得到sqrt(2-2*-1)= 2
。这显然是一个简单的形状,因此你可以通过归一化数据然后使用欧几里得距离来获得与余弦距离相同的排序。只要你使用uniform
权重选项,结果将与使用正确的余弦距离相同。