赞
踩
(1)密度直达、密度可达、密度相连都属于同一个簇;
(2)密度直达、密度可达不具有对称性,密度相连具有对称性。
一个思想:直观上看,DBSCAN可以找到样本点中全部的密集区域,并把他们当作一个一个的聚类簇。
两个算法参数:① 邻域半径epsilon;② 最小点数minPts(用来定量刻画什么叫“密集”)。
三种点类别:核心点、边界点、噪声点。
四种点间关系:密度直达、密度可达、密度相连。
两个实现步骤:① 找到所有核心点,并将其密度直达的点形成对应的临时聚类簇;② 对于每个临时聚类簇,检查其中的点是否是核心点,如果是,则将该点对应的临时聚类簇和当前聚类簇合并。重复以上步骤,直到所有的核心点和边界点都完成聚类。
优点:
(1)不需要事先设定簇的个数;
(2)不需要假设簇的形状,能够识别任意形状的簇;
(3)对异常值不敏感,可以将不属于任何簇的点标记为噪声。
缺点:
(1)如果样本密度分布不均匀,聚类效果较差;
(2)样本集较大时,收敛时间较长;
(3)有两个参数,比K-Means参数更多,更难调参。
# DBSCAN算法核心过程
def DBSCAN(data, eps, minPts):
n, m = data.shape
disMat = compute_squared_EDM(data) # 获得距离矩阵
core_points_index = np.where(np.sum(np.where(disMat <= eps, 1, 0), axis=1) >= minPts)[0] # 计算核心点索引
labels = np.full((n,), -1) # 初始化类别,-1代表未分类。
clusterId = 0
for pointId in core_points_index: # 遍历所有的核心点
if (labels[pointId] == -1): # 如果核心点未被分类,将其作为的种子点,开始寻找相应簇集
labels[pointId] = clusterId # 首先将点pointId标记为当前类别(即标识为已操作)
seeds = set(np.where((disMat[:, pointId] <= eps) & (labels==-1))[0]) # 种子点集(核心点的eps邻域且没有被分类的点 )
while len(seeds) > 0: # 通过种子点,开始生长,寻找密度可达的数据点,一直到种子集合为空,一个簇集寻找完毕
newPoint = seeds.pop()
labels[newPoint] = clusterId # 将newPoint标记为当前类
queryResults = np.where(disMat[:,newPoint]<=eps)[0] # 种子点的eps邻域(包含自己)
if len(queryResults) >= minPts: # 如果newPoint属于核心点,那么newPoint是可以扩展的,即密度是可以通过newPoint继续密度可达的
for resultPoint in queryResults:
if labels[resultPoint] == -1: # 将邻域内且没有被分类的点压入种子集合
seeds.add(resultPoint)
clusterId = clusterId + 1 # 簇集生长完毕,寻找到一个类别
return labels
机器学习模型自我代码复现:DBSCAN_密度可达和密度相连的区别-CSDN博客
(本文完整的pdf请关注“张张学算法”,并回复“029”获取~)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。