python中余弦度量的DBSCAN错误
Posted
技术标签:
【中文标题】python中余弦度量的DBSCAN错误【英文标题】:DBSCAN error with cosine metric in python 【发布时间】:2015-12-21 02:57:47 【问题描述】:我试图将 scikit-learn 库中的 DBSCAN 算法与余弦度量一起使用,但遇到了错误。 代码行是
db = DBSCAN(eps=1, min_samples=2, metric='cosine').fit(X)
其中X
是csr_matrix
。错误如下:
度量“余弦”对算法“自动”无效,
虽然文档说可以使用此指标。
我尝试使用选项 algorithm='kd_tree'
和 'ball_tree'
但得到了相同的结果。但是,如果我使用euclidean
或者说l1
度量标准,则不会出现错误。
矩阵X
很大,所以我不能使用成对距离的预计算矩阵。
我使用python 2.7.6
和scikit-learn 0.16.1
。
我的数据集没有一整行零,因此余弦度量是明确定义的。
【问题讨论】:
坦率地说,这可以说是 sklearn 中的一个错误。余弦相似度不是度量标准。它不遵守三角不等式,这就是为什么它不能与 KDTree 一起使用,你别无选择,只能强行使用它。所有这些都提出了一个问题,为什么当您将算法设置为“自动”时,它会尝试使用它应该知道它不能使用的方法。 @AdamAcosta:如果我理解正确,您是在争辩'auto'
algorithm
-关键字应该使用 'brute'
而不是尝试使用 'ball_tree'
失败? (我同意。)
【参考方案1】:
如果您想要一个像余弦距离这样的标准化距离,您也可以先标准化您的向量,然后使用欧几里得度量。请注意,对于两个归一化向量 u 和 v,欧式距离等于 sqrt(2-2*cos(u, v)) (see this discussion)
因此,您可以执行以下操作:
Xnorm = np.linalg.norm(X,axis = 1)
Xnormed = np.divide(X,Xnorm.reshape(Xnorm.shape[0],1))
db = DBSCAN(eps=0.5, min_samples=2, metric='euclidean').fit(Xnormed)
距离将位于 [0,2] 范围内,因此请确保相应地调整参数。
【讨论】:
如果是这样的话,您能否进一步说明为什么使用 euclidian-distance-on-normalised-vectors 的 DBSCAN 算法会产生与直接余弦距离相同的结果?特别是平方/平方根是什么,余弦真正衡量相似度而不是距离是否重要(距离是1-cos(.;.)
)
例如,如果您知道eps
应设置为具有余弦距离的x
,那么在使用带有euclid
的DBSCAN 时应将其设置为sqrt(x)
。而且,如果是这样的数据,sklearn 索引是否可以完成其紧固目的?【参考方案2】:
sklearn 中的索引(可能 - 这可能会随着新版本的变化而改变)无法加速余弦。
试试algorithm='brute'
。
有关您的 sklearn 版本可以加速的指标列表,请参阅球树支持的指标:
from sklearn.neighbors.ball_tree import BallTree
print(BallTree.valid_metrics)
【讨论】:
谢谢!现在它起作用了。首先,它给了我一个错误,因为我使用np.float32
而不是np.double
作为我的数据集。我认为 DBSCAN 需要余弦度量的这种精度,因为后者的范围很小(在 0 和 1 之间)。
一般来说应该没有必要,但是sklearn的实现可能会有这样的限制。
截至今天(2019 年 10 月),“粗略”算法不起作用,但“通用”算法可以。如前所述,.fit 方法需要双精度以上是关于python中余弦度量的DBSCAN错误的主要内容,如果未能解决你的问题,请参考以下文章
Python:使用 scikit-learn 的 dbscan 进行字符串聚类,使用 Levenshtein 距离作为度量: