使用DBSCAN找到最密集的聚类?

4 投票
3 回答
5607 浏览
提问于 2025-05-11 02:23

我一直在看Geoff Boeing写的关于DBSCAN的精彩博客文章。我最感兴趣的页面是 -

http://geoffboeing.com/2014/08/clustering-to-reduce-spatial-data-set-size/

我该如何修改这个方法,以便找到最大的聚类中心(也就是周围有最多经纬度点的那个中心)?每个聚类的中心点有没有一个密度评分呢?

核心的dbscan -

db = DBSCAN(eps=.01, min_samples=1).fit(coordinates)
labels = db.labels_
num_clusters = len(set(labels)) - (1 if -1 in labels else 0)
clusters = pd.Series([coordinates[labels == i] for i in xrange(num_clusters)])
print('Number of clusters: %d' % num_clusters)

相关文章:

  • 暂无相关问题
暂无标签

3 个回答

1

我也在做一个类似的项目,并且也在参考他的博客文章。关于如何找到最大聚类的中心点的逻辑是这样的:先把聚类按大小排序,选出最大的那个,然后计算它的中心点(可以用那篇博客里提供的方法)。接下来你有两个选择。你可以把这个计算出来的中心点当作“中心点”,或者你可以找出聚类中离这个中心点最近的那个点(就像那篇博客的作者所做的)。

与其他回答者不同的是,那篇博客在很多方面并没有错误:

  1. 单链接聚类在很多情况下是完全可以用的,包括博客作者所用的场景。
  2. 他的eps值是合适的,并且是根据他的使用情况精心选择的,他明确说明这是为了去除近似重复的数据。
  3. 关于聚类中心,那篇博客并没有错误,实际上它明确提到了非凸性,并且代码返回的是聚类中的一个点,而不是聚类的中心点。
  4. 博客中的代码在进行DBSCAN聚类时确实使用了通过哈弗辛公式计算的大圆距离。

最重要的是,结果正如博客中所描述的那样,完全符合预期。

1

如果你想把最大的聚类表示为一个“中心”点(比如说,降维处理),我会这样做:

首先,找出分类点最多的那个聚类:

# Assumes coordinates is a DataFrame
db = DBSCAN(eps=eps, min_samples=min_samples).fit(coordinates)
df = pd.DataFrame([coordinates.x, coordinates.y, db.labels_]).T # Add other attributes of coordinates if needed
df.columns = ['x', 'y','label']; # Add column names
max_label = df.label.mode()[0];

max_cluster = df[df['label']==max_label];

然后,你可以计算每一列的平均值。

max_cluster_array = max_cluster[['x','y']].as_matrix()
print max_cluster_array.mean(axis=0) # what you are looking for

如果你想更准确地估计一个“中心”点,你也可以看看多变量核密度估计的相关函数。

1

很遗憾,那篇博客文章在几个关键点上是错误的。

  1. 绝对不要把DBSCAN的参数min_samples=1。这实际上是单链接聚类。如果你想要单链接聚类,就直接用单链接聚类,而不是DBSCAN。在这里,Leader聚类也是一个不错的选择。

  2. 选择eps时要谨慎。在他的例子中,他选择的eps值太小,导致大部分(近似)重复的数据被去掉了……

  3. DBSCAN聚类没有一个有意义的中心。因为它们可能是非凸的。特别是,中心需要考虑哈弗辛距离,但他没有做到。最初的版本使用了平均值,而新版本使用的是离平均值最近的点(但这可能仍然有偏差,因为平均值没有考虑地球的形状)。

  4. 在进行聚类时,你应该使用大圆距离来计算经纬度,而不仅仅是在之后使用。(现在博客中已经修正了这个问题)。

上面提到的第3点也回答了你的问题:DBSCAN聚类可能没有一个有意义的中心。这个中心可能在聚类之外

自从原始帖子发布以来,一些内容(特别是第4点)已经得到了改进。现在DBSCAN实际上使用了哈弗辛距离和球树索引。

撰写回答