DBSCAN聚类算法
DBSCAN聚类算法介绍
基本算法思想
DBSCAN是一种基于密度的聚类算法,这类密度聚类算法一般假定类别可以通过样本分布的紧密程度决定。同一类别的样本,他们之间的紧密相连的,也就是说,在该类别任意样本周围不远处一定有同类别的样本存在。
通过将紧密相连的样本划为一类,这样就得到了一个聚类类别。通过将所有各组紧密相连的样本划为各个不同的类别,则我们就得到了最终的所有聚类类别结果。
算法原理和步骤
1. 密度定义
DBSCAN使用一组参数 (\(\epsilon\),MinPts) 来描述样本密度。参数 \(\epsilon\) 表示一个半径,用来定义数据点之间的邻域;参数MinPts表示一个点在 \(\epsilon\) 半径范围内最少需要包含的点数目,用来描述核心点周围的密度。
假如我们有样本集 \(\mathbf{D}\) = ( \({x_1,x_2,x_3,...,x_n}\) ),则DBSCAN具体的密度描述定义如下:
- \(\epsilon-邻域:\) 对于 \({x_j} \in \mathbf{D}\),其\(\epsilon\)-邻域包含样本集合D中与\({x_j}\)的距离不大于\(\epsilon\)的子样本集,即 \[ \mathbf{N_\epsilon}(x_j)=\left\{ x_i \ \epsilon\ \mathbf{D}\ |\ \mathbb{distance(x_i,x_j) \leq \epsilon} \right\} \tag{1} \]
- 核心点: 如果\({x_j}\)的\(\epsilon\)-邻域包含的样本点数目大于等于MinPts,即
\[
\left| \mathbf{N_\epsilon}(x_j) \right| \geq MinPts
\tag{2}
\]
,则称\({x_j}\)为核心点。
- 核心点: 如果\({x_j}\)的\(\epsilon\)-邻域包含的样本点数目大于等于MinPts,即
\[
\left| \mathbf{N_\epsilon}(x_j) \right| \geq MinPts
\tag{2}
\]
- 密度直达: 如果\({x_i}\)位于\({x_j}\)的\(\epsilon\)-邻域内,且\({x_j}\)为核心点,则称\({x_i}\)由\({x_j}\) 密度直达。 密度直达起点必须是核心点;终点必须在\(\epsilon-\)邻域内
- 密度可达: 如果存在样本序列\({p_1,p_2,...,p_n}\),满足\({p_1}=x_i\),\({p_n}=x_j\),且\({p_{k+1}}\)由\({p_k}\)(其中\(k=1,2,...,n-1\))密度直达,则称\({x_j}\)由\({x_i}\)密度可达。密度可达的起点必须是核心点;中间链路上的点也必须是核心点;终点可以是任意点
- 密度相连: 如果存在样本\({x_k}\),使得\({x_i}\)和\({x_j}\)都由\({x_k}\)密度可达,则称\({x_i}\)和\({x_j}\)密度相连。
2. DBSCAN算法步骤
输入:样本集合\(\mathbf{D}=({x_1,x_2,x_3,...,x_n}\)),邻域参数\((\epsilon,MinPts)\)
输出: 簇划分 \(C\)
初始化核心点集合 \(\Omega=\emptyset\) 为空集,初始化聚类簇数k=0,初始化未访问样本集合\(\Gamma=D\) ,簇划分\(C=\emptyset\)
对于i=1,2,...,n的样本\({x_i}\),执行以下步骤找出所有的核心对象:
- 通过距离度量函数,找出样本\({x_i}\)的\(\epsilon\)领域范围的子样本集合\(\mathbf{N_\epsilon}(x_i)\)
- 如果\(\left| \mathbf{N_\epsilon}(x_i) \right| \geq MinPts\),则将\({x_i}\)加入核心点集合 \(\Omega=\Omega \ \cup\ \left\{ x_i\right\}\)
假如 \(\Omega=\emptyset\),则返回,否则执行
步骤4
在核心对象集 \(\Omega\) 中,随机选择一个核心对象\(x_i\),初始化当前簇核心对象队列 \(\Omega_{cur}=\left\{x_i\right\}\),初始化类别序列号k=k+1,初始化当前簇样本\(C_k=\left\{x_i\right\}\),更新未访问对象样本集合\(\Gamma=\Gamma - \left\{x_i\right\}\)
如果当前簇队列\(\Omega_{cur}=\emptyset\),表示当前簇\(C_k\)生成完成,更新簇 \(C=\left\{C_1,C_2,...C_k \right\}\) 更新核心对象集 \(\Omega=\Omega-C_k\) 转入
步骤3
,否则更新核心对象集 \(\Omega=\Omega-C_K\)在当前簇队列\(\Omega_{cur}\)中取一个核心对象\(x_j\),通过邻域距离阈值\(\epsilon\)-邻域子样本集\(N_\epsilon(x_j)\),令\(\Delta=N_\epsilon(x_j)\cap\Gamma\),更新当前簇样本集合\(C_k=C_k\cup\Delta\),更新未访问样本集合\(\Gamma=\Gamma-\Delta\),更新当前访问队列\(\Omega_{cur}=\Omega_{cur}\cup(\Delta\cap\Omega)-x_j\),转入
步骤5
输出结果为 簇划分\(C=\left\{C_1,C_2,...,C_k \right\}\)
3. 基于java实现的通用代码逻辑
1 |
|