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)    

其中Xcsr_matrix。错误如下:

度量“余弦”对算法“自动”无效,

虽然文档说可以使用此指标。 我尝试使用选项 algorithm='kd_tree''ball_tree' 但得到了相同的结果。但是,如果我使用euclidean 或者说l1 度量标准,则不会出现错误。

矩阵X 很大,所以我不能使用成对距离的预计算矩阵。

我使用python 2.7.6scikit-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 距离作为度量:

在 python 中的 sklearn 中绘制 DBSCAN 中的特定点

聚类算法讲解:KMEANS和DBSCAN

距离度量以及python实现

距离度量以及python实现

Python:3 维空间中的 DBSCAN