使用DBSCAN对角度数据进行聚类

0 投票
2 回答
568 浏览
提问于 2025-04-18 08:27

我需要把一些数据点分成不同的组,这些数据点的格式是X,Y,Phi。现在我使用的是DBSCAN这个工具(来自sklearn库)。分组的效果还不错,但有一个问题:Phi是角度数据,它的范围是0到2π(也就是360度)。所以在Phi接近0的地方,分组的结果就不太对了。有没有什么办法可以解决这个问题?我自己找不到合适的办法,也想不出什么有效的解决方案。

谢谢。

2 个回答

1

DBSCAN可以处理任意距离

所以首先你需要定义一个距离函数(这可能会用到一些三角函数),然后把这个函数放进DBSCAN里作为相似度的计算方式。

你可以尝试用下面这样的方式:

distance = (x1-x2)**2 + (y1-y1)**2 + factor * sin(phi1-phi2)**2

不过你需要仔细选择你的权重factor,因为角度差异和你的XY轴是不同的量级,我想是这样的。

在这个数据集上不要使用欧几里得距离,原因很明显。

2

圆形边界条件在实际操作中不太容易实现,特别是在没有傅里叶框架的情况下。

你可以尝试通过重新参数化来解决这个问题,也就是用 X, Y, a * cos(Phi), a * sin(Phi) 来替换 X, Y, Phi。这里的 a > 0 是一个缩放因子,需要正确选择,这样才能让这个投影在二维空间中按你需要的方式进行聚类。可以先试试 a = 1(如果在纯 Phi 的情况下效果不错,那这个值就很合适),然后再根据你剩下的数据 X, Y 的数量级来调整 a

这样做的想法是把 Phi 替换成它的“真实”复杂“含义”,也就是 相位,即 exp(1j * Phi),但在整个过程中保持它是实数。

接下来,你需要基于这个重新参数化的结果来计算距离,比如欧几里得距离:

dist = ((np.array([X1, Y1, a* np.cos(Phi1), a * np.sin(Phi1)]) - np.array([X2, Y2, a * np.cos(Phi2), a * np.sin(Phi2)])) ** 2).sum()

你需要对每一对数据进行这样的计算,然后再把结果输入到你的 DBSCAN 对象中。

撰写回答