DBSCAN 密度聚类 Python实现

本文详细介绍了DBSCAN密度聚类算法的工作原理,通过实例解释了如何找到核心点集合,逐步构建聚类簇,并给出了Python代码实现。文章强调了DBSCAN算法对超参数的敏感性以及在处理异常值上的优势。

DBSCAN是一种利用样本“密度”信息进行聚类的算法,有两个超参数,一个是核心点的邻域半径,一个是核心点邻域内拥有的点的个数(包括自己)。

看了网上不少算法流程,大多说得模棱两可。。有的还是错的。。比如将同一个点分入到了两个不同的类,然后把这个两个类“结合”成一个。

我理解的原理就是:

①由邻域半径和点的个数,找到核心点的集合,以西瓜书为例,假设是[3,5,6,8,9,13,14,18,19,24,25,28,29]。

②从该点随机抽出一个点,比如8,找到8邻域内的所有点:[6,7,8,18,19],与整个样本集合取交集,得到一个簇[6,7,8,18,19]。

③把8从核心点去掉,把该簇从整个样本去掉。找到8邻域内中的核心点,这里是[6,18,19],再分别以6/18/19,重复以上过程。

④直到最后找到的点不是核心点。

是个递归的过程

如图所示:从8出发,找到了[6,7,18,19],7不是核心点,不管,加入簇并从整体样本剔除。再从6出发,找到了[8,19,18,23],8,19,18,已经从整个样本剔除了,所以与整个样本的交集,就是23号,23号不是核心点,所以对于6的搜索完成了,再把23加入到簇并从整个样本剔除。再从18出发,找到了[6,8,12,19,20],6,8,19,已经从整个样本剔除了,交集只有12、20,12和20,又不是核心点,所以对于18的搜索完成,12和20加入到簇,并从整个样本剔除。最后从19出发,找到[8,18,20,10],与整个样本交集只有10,(虽然19也找到了20,但是20已经在簇里面了,而且没在整个样本,交集取不到),所以把10加入到簇。这样,一个簇就聚类完成。结果就是西瓜书的一个簇:

### 使用Python实现DBSCAN算法对点云数据进行聚类分析 #### 1. 导入必要的库 为了使用DBSCAN算法对点云数据进行聚类,通常会依赖于`scikit-learn`中的DBSCAN模块以及其他辅助工具如`numpy`和可视化库`matplotlib`。如果涉及到三维点云的操作,则可能会用到专门处理这类数据的库——`open3d`。 ```python import numpy as np from sklearn.cluster import DBSCAN import matplotlib.pyplot as plt import open3d as o3d ``` #### 2. 加载或创建点云数据集 可以通过读取文件或其他方式获取点云数据。这里假设已经有一个名为`point_cloud_data.npy`的数据文件存储着点坐标信息。 ```python # 假设我们已经有了一个保存好的点云数据文件 points = np.load('point_cloud_data.npy') # 或者直接生成一些随机测试数据用于演示目的 np.random.seed(0) n_points_per_cluster = 250 blobs = [] for i in range(3): blob_center_x, blob_center_y, blob_center_z = (i * 8), (-1)**i*7+i*(-1)**(i+1)*4, ((-1)**i)*9+(i//2)*(-1)**((i+1)//2)*6 blobs.append(np.random.randn(n_points_per_cluster, 3) + [blob_center_x,blob_center_y,blob_center_z]) points = np.vstack(blobs) pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(points) o3d.visualization.draw_geometries([pcd]) # 可视化原始点云 ``` #### 3. 应用DBSCAN算法进行聚类 设置合适的参数(比如半径eps和最小样本数min_samples),并调用fit方法完成聚类过程。 ```python db = DBSCAN(eps=0.3, min_samples=10).fit(points) labels = db.labels_ # 获取核心样本索引和其他属性 core_samples_mask = np.zeros_like(labels, dtype=bool) core_samples_mask[db.core_sample_indices_] = True unique_labels = set(labels) colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))] ``` #### 4. 结果展示 最后一步是对聚类后的结果进行可视化表示,以便直观理解不同簇之间的分布情况。 ```python fig = plt.figure(figsize=(10, 7)) ax = fig.add_subplot(projection='3d') for k, col in zip(unique_labels, colors): if k == -1: # 黑色代表噪声点 col = [0, 0, 0, 1] class_member_mask = labels == k xyz = points[class_member_mask & core_samples_mask] ax.scatter(xyz[:, 0], xyz[:, 1], xyz[:, 2], 'o', c=[col]) xyz = points[class_member_mask & ~core_samples_mask] ax.scatter(xyz[:, 0], xyz[:, 1], xyz[:, 2], 'o', c=[col], marker="x") plt.title('Estimated number of clusters: %d' % len(set(labels)-(set([-1])))) plt.show() # 同样也可以通过Open3D来进行更高级别的渲染 label_colors = np.array([[1, 0, 0] if l != -1 else [0, 0, 0] for l in labels]) pcd.colors = o3d.utility.Vector3dVector(label_colors) o3d.visualization.draw_geometries([pcd]) ``` 上述流程展示了如何利用Python及其相关库来实施基于密度的空间聚类应用(DBSCAN),特别是针对点云数据的情况[^1][^2][^3].
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值