一、基本概念
可以用1,2,3,4来总结DBSCAN的基本概念。
1个核心思想:基于密度
直观效果上看,DBSCAN算法可以找到样本点的全部密集区域,并把这些密集区域当做一个一个的聚类簇。
2个算法参数:邻域半径R和最少点数目minpoints
这两个算法参数实际可以刻画什么叫密集——当邻域半径R内的点的个数大于最少点数目minpoints时,就是密集。
3种点的类别:核心点,边界点和噪声点
邻域半径R内样本点的数量大于等于minpoints的点叫做核心点。不属于核心点但在某个核心点的邻域内的点叫做边界点。既不是核心点也不是边界点的是噪声点。
4种关系:密度直达,密度可达,密度相连,非密度相连
如果P为核心点,Q在P的R邻域内,那么称P到Q密度直达。任何核心点到其自身密度直达,密度直达不具有对称性,如果P到Q密度直达,那么Q到P不一定密度直达。
如果存在核心点P2,P3,……,Pn,且P1到P2密度直达,P2到P3密度直达,……,P(n-1)到Pn密度直达,Pn到Q密度直达,则P1到Q密度可达。密度可达也不具有对称性。
如果存在核心点S,使得S到P和Q都密度可达,则P和Q密度相连。密度相连具有对称性,如果P和Q密度相连,那么Q和P也一定密度相连。密度相连的两个点属于同一个聚类簇。
如果两个点不属于密度相连关系,则两个点非密度相连。非密度相连的两个点属于不同的聚类簇,或者其中存在噪声点。
二、算法描述
DBSCAN 算法对簇的定义很简单,由密度可达关系导出的最大密度相连的样本集合,即为最终聚类的一个簇。
DBSCAN 算法的簇里面可以有一个或者多个核心点。如果只有一个核心点,则簇里其他的非核心点样本都在这个核心点的 Eps 邻域里。如果有多个核心点,则簇里的任意一个核心点的 Eps 邻域中一定有一个其他的核心点,否则这两个核心点无法密度可达。这些核心点的 Eps 邻域里所有的样本的集合组成一个 DBSCAN 聚类簇。
DBSCAN算法的描述如下。
输入:数据集,邻域半径 Eps,邻域中数据对象数目阈值 MinPts;
输出:密度联通簇。
处理流程如下。
1)从数据集中任意选取一个数据对象点 p;
2)如果对于参数 Eps 和 MinPts,所选取的数据对象点 p 为核心点,则找出所有从 p 密度可达的数据对象点,形成一个簇;
3)如果选取的数据对象点 p 是边缘点,选取另一个数据对象点;
4)重复(2)、(3)步,直到所有点被处理。
DBSCAN 算法的计算复杂的度为 O(n²),n 为数据对象的数目。这种算法对于输入参数 Eps 和 MinPts 是敏感的。
代码实现逻辑如下:
1)计算每个point的eps范围内的point数量pts;
2)对于所有pts >Minpts的point,记为Core point;
3)对于所有的corepoint,将其eps范围内的core point下标添加到vector集合(vector neighborCoreIdx)中;
4)遍历所有的corepoint,采用深度优先的方式遍历它的neighborCoreIdx集合,使得相互连接的core point具有相同的cluster编号;
5)对所有pts < Minpts且在Core point 范围内的点,记为Borderpoint;
若某个Borderpoint点在某个Core point的eps范围内,则让该Borderpoint点的cluster编号等于这个Core point的cluster编号;
6)剩余的point的为Noise point;
程序结束。
三、代码实现
看了几个其他博客的代码,但是感觉很乱,有的运行出错,或者是展示效果差。本人自己整理了一份可以使用和展示的代码,运行无误! 加了很多帮助理解的注释,浅显易懂!
#include
#include
#include
#include
#include
#include
#include
#include
#include
附程序所使用的dataset.txt文件:
0,0
3,8
2,2
1,1
5,3
4,8
6,3
5,4
6,4
7,5
12,4
12,5
12,6
13,4
17,8
18,9
四、代码运行效果
五、参考资料
鸣谢:
聚类算法-DBSCAN-C++实现_k76853的专栏-CSDN博客_c++ dbscan
DBSCAN详解_hansome_hong的博客-CSDN博客_dbscan