DBSCAN,Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类算法

 

VS KMeans

Kmeans 是最常用的聚类算法之一,但它只适用于 凸样本集,而 DBSCAN 适用于 凸样本集和非凸样本集,更多的用于 非凸样本集;

记住这一点即可:Kmeans 只能生成球形簇,DBSCAN 可以生成任意形状的簇

 

算法原理

DBSCAN 是一种基于密度的聚类算法,其核心是根据样本分布的紧密程度来划分类别

形象描述

DBSCAN 的原理类似传销,传销组织会分成一个个窝点(类别),就是一拨人租个房;

起初窝点里只有一个人(随机找一个点);

然后这个人(核心对象)有很多亲戚朋友(关系近),他就通过骗取亲戚朋友发展下线(直接下线叫密度直达),骗来的人也住进了窝点;

然后每个下线(新的核心对象)也有很多亲戚朋友,也通过同样的方式发展自己的下线,然后下线的下线也住进了窝点;

上上线 和 新来的下线(间接下线) 通过 上线 住进了一个窝点(密度可达),也就成了一类;

然后循环往复,直到某个人周围没有亲戚朋友(边界点),完了,生意做不下去了;

但最终这个窝点的人都认识了(密度相连);

 

另起一个窝点吧(新的类别),

重复上面的过程,最终形成一个个窝点;

 

可能有些窝点很特别,当这个窝点只有一个人时,这个人周围就已经没有亲戚朋友了,这个窝点就没用了(孤立点,异常值)

 

数学描述

DBSCAN 通过不断寻找核心对象来确定样本类别,其中有两个重要参数 (ε,MinPts);

假设我的样本集是D=(x1,x2,...,xm), 则DBSCAN具体的描述定义如下:

1)ϵ-邻域:对于xj€D,其ϵ-邻域包含样本集D中与xj的距离不大于ϵ的子样本集,【在 xj 周围画个 以 ε 为半径的圆】

2 ) 核心对象:对于任一样本xj€D,如果其ϵ-邻域内至少包含MinPts个样本,则称其是核心对象。 【在 xj 周围画个半径为 ε 的圆,圆内的样本数大于等于 MinPts 】

3)密度直达:如果xi位于xj的ϵ-邻域中,且xj是核心对象,则称xi由xj密度直达。【圆心 和 圆内的点 叫密度直达】

注意反之不一定成立,即此时不能说xj由xi密度直达, 除非且xi也是核心对象。

4)密度可达:对于xi和xj,如果存在样本序列p1,p2,...,pT,满足p1=xi,pT=xj, 且pt+1由pt密度直达,则称x由xi密度可达。

也就是说,密度可达满足传递性。此时序列中的传递样本p1,p2,...,pT−1均为核心对象,因为只有核心对象才能使其他样本密度直达。

注意密度可达也不满足对称性,这个可以由密度直达的不对称性得出。

5)密度相连:对于xi和xj,如果存在核心对象样本xk,使xi和xj均由xk密度可达,则称xi和xj密度相连。注意密度相连关系是满足对称性的。

 

从下图可以很容易理解上述定义,图中MinPts=5,红色的点都是核心对象,因为其ϵ-邻域至少有5个样本。黑色的样本是非核心对象。

所有核心对象密度直达的样本在以红色核心对象为中心的超球体内,如果不在超球体内,则不能密度直达。

图中用绿色箭头连起来的核心对象组成了密度可达的样本序列。在这些密度可达的样本序列的ϵ-邻域内所有的样本相互都是密度相连的。

DBSCAN 还有3个点描述:

  • 核心点:即核心对象,core point
  • 边界点:与某个核心对象密度直达,但其邻域内少于 MinPts 个点,但他仍被归于和核心对象一个簇,border point
  • 离群点:也叫异常值,不和任意核心对象密度直达,自己也不是核心对象,outlier point

 

算法步骤

找了个图,思路还是比较清晰的

注意, 某些样本可能到两个核心对象的距离都小于ϵ,但是这两个核心对象不是密度直达,不属于同一个聚类簇,那么如何界定这个样本的类别呢?

一般来说,DBSCAN采用先来后到,先进行聚类的类别簇会标记这个样本为它的类别。也就是说DBSCAN的算法不是完全稳定的算法

 

优点

1. 无需指定 类别数 K

2. 对异常值不敏感

3. 可以形成任意形状的簇

 

缺点

1. 对于分布紧密程度比较均匀的样本集不太适用

2. 对于样本集很大,维度很高的样本集,计算量太大,效率较低  【此时可以对搜索最近邻时建立的KD树或者球树进行规模限制来改进。】

3. 受 (ε,MinPts) 参数影响较大

 

Sklearn 用法

核心参数

def __init__(self, eps=0.5, min_samples=5, metric='euclidean',
                 metric_params=None, algorithm='auto', leaf_size=30, p=None,
                 n_jobs=1):

metric 可指定计算距离的方式

返回值

core_sample_indices_ : 核心点的索引,因为labels_不能区分核心点还是边界点,所以需要用这个索引确定核心点

components_:训练样本的核心点

labels_:每个点所属集群的标签,-1代表噪声点


示例代码
import numpy as np
from sklearn.cluster import DBSCAN

X = np.array([[1, 2], [2, 2], [2, 3], [-25, -80],
             [8, 7], [8, 8], [25, 80], [6, 8]])
clustering = DBSCAN(eps=3, min_samples=2).fit(X)
print(clustering.labels_)       # [ 0  0  0 -1  1  1 -1  1]     异常点被标记为-1

index = clustering.core_sample_indices_     # 核心对象的下标
print(index)                    # [0 1 2 4 5 7]

core_sample = X[index]      # 核心对象
print(core_sample)
# [[1 2]
#  [2 2]
#  [2 3]
#  [8 7]
#  [8 8]
#  [6 8]]

print(clustering.components_)   # 核心对象,同上
# [[1 2]
#  [2 2]
#  [2 3]
#  [8 7]
#  [8 8]
#  [6 8]]

 

 

 

参考资料:

https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html  官网

https://www.cnblogs.com/pinard/p/6208966.html  DBSCAN密度聚类算法

https://www.cnblogs.com/pinard/p/6217852.html  用scikit-learn学习DBSCAN聚类

https://zhuanlan.zhihu.com/p/185623849  详解DBSCAN聚类

https://www.jianshu.com/p/e594c2ce0ac0  DBSCAN 算法