我想使用具有度量sklearn.metrics.pairwise.cosine_similarity的DBSCAN来聚类具有接近于1的余弦相似性的点(即,其矢量(来自“原点”)是平行的或几乎平行的)。
问题:
eps是两个样本之间的最大距离,它们被DBSCAN认为是在同一邻域中 - 意味着如果两点之间的距离小于或等于eps,则这些点被认为是邻居;
但
sklearn.metrics.pairwise.cosine_similarity吐出介于-1和1之间的值,并且我希望DBSCAN将两个点视为邻居,如果它们之间的距离例如在0.75和1之间 - 即大于或等于0.75。
我看到两种可能的解决方案
我不知道如何实现其中任何一个。
任何指导将不胜感激!
DBSCAN
有一个metric
关键字参数。文档字符串:
metric:string或callable计算要素数组中实例之间距离时使用的度量标准。如果metric是字符串或可调用的,则它必须是metrics.pairwise.calculate_distance为其度量参数所允许的选项之一。如果度量是“预先计算的”,则假定X是距离矩阵,并且必须是正方形。 X可以是稀疏矩阵,在这种情况下,只有“非零”元素可以被认为是DBSCAN的邻居。
因此,最简单的做法是使用余弦相似度预先计算距离矩阵作为距离度量,预处理距离矩阵使其符合您的定制距离标准(可能类似于D = np.abs(np.abs(CD) -1)
,其中CD是您的余弦距离矩阵),然后将metric
设置为precomputed
,并将预先计算的距离矩阵D
传递给X
,即数据。
例如:
#!/usr/bin/env python
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import DBSCAN
total_samples = 1000
dimensionality = 3
points = np.random.rand(total_samples, dimensionality)
cosine_distance = cosine_similarity(points)
# option 1) vectors are close to each other if they are parallel
bespoke_distance = np.abs(np.abs(cosine_distance) -1)
# option 2) vectors are close to each other if they point in the same direction
bespoke_distance = np.abs(cosine_distance - 1)
results = DBSCAN(metric='precomputed', eps=0.25).fit(bespoke_distance)
A)查看广义DBSCAN,它的相似性也很好。对于余弦,无论如何,sklearn应该会很慢。
B)你可以平凡地使用:余弦距离= 1 - 余弦相似度。但这可能会导致sklearn实现在O(n²)中运行。
C)你甚至可以将-cosinesimilarity
作为预先计算的距离矩阵传递,并使用-0.75作为eps。
d)只做一个二进制距离矩阵(在O(n²)存储器中,但是很慢),其中余弦相似度的距离= 0大于你的阈值,否则为0。然后使用eps = 0.5的DBSCAN。当且仅当相似性>阈值时,显示距离<eps是微不足道的。