DBSCAN基本介绍
DBSCAN 是一种著名的密度聚类算法,它基于一组“邻域”(neighborhood)参数(ε,MinPts)来刻画样本分布的紧密程度.给定数据集D={},
定义下面这几个概念:

DBSCAN定义的基本概念(MinPts = 3):虚线显示出ε-邻域, 是核心对象,
由
密度直达,
由
密度可达,
与
密度相连.由上图我们可以直观地理解概念
基于这些概念,DBSCAN将“簇”定义为: 由密度可达关系导出的最大的密度相连样本集合.形式化地说,给定邻域参数(ε, MinPts),簇∈
是满足以下性质的非空样本子集:
连接性(connectivity ): ∈
,
∈
与
密度相连
最大性(maximality): ∈
,
由
密度可达
∈
那么,如何从数据集D中找出满足以上性质的聚类簇呢?实际上,若为核心对象,由
密度可达的所有样本组成的集合记为
= {
∈
由
密度可达},则不难证明
即为满足连接性与最大性的簇.
于是,DBSCAN算法先任选数据集中的一个核心对象为“种子”(seed),再由此出发确定相应的聚类簇,算法描述如图下图所示.在第1~7行中,算法先根据给定的邻域参数(ε, MinPts)找出所有核心对象;然后在第10~24行中,以任一核心对象为出发点,找出由其密度可达的样本生成聚类簇,直到所有核心对象均被访问过为止.
伪代码展示:

此处有一个可视化网站:
Visualizing DBSCAN Clustering (naftaliharris.com)
通过这个网站,我们可以直观地看到DBSCAN的聚类过程
算法的不稳定
某个样本可能到两个核心对象的距离都小于Eps,但是这两个核心对象由于不是密度直达,又不属于同一个聚类簇,那么如果界定这个样本的类别呢?如图这个蓝点该分给哪个簇呢?
一般来说,此时DBSCAN采用先来后到,先进行聚类的类别簇会标记这个样本为它的类别。也就是说BDSCAN的算法不是完全稳定的算法。
代码展示,python
次代码没有根据上述伪代码编写
import numpy as np
import matplotlib.pyplot as plt
def distance(x, y):
return np.linalg.norm(x - y)
def find_neighbors(center, eps, data):
"""
找出中心点的邻近点
:param center: 中心点
:param eps: 半径
:param data: 数据集
:return: 返回邻近点在data的索引
"""
neighbors = []
N, D = data.shape
for i in range(N):
if distance(center, data[i,:]) < eps:
neighbors.append(i)
return neighbors
def DBscan(data, eps, min_samples):
N, D = data.shape
labels = np.full(N, -1) # 默认为-1噪声点
cluster = 0
for i in range(N):
if labels[i] != -1: # 判断是否已经分类,是则遍历下一个
continue
# 该索引点的邻域点
neighbors = find_neighbors(data[i,:], eps, data)
# 邻域点为1则表示为噪声点,直接下一个
if len(neighbors) == 1:
continue
# 判断是否为核心点,是则执行拓展聚类
elif len(neighbors) >= min_samples:
labels[i] = cluster
expand_cluster(data, labels, neighbors, eps, min_samples, cluster)
cluster += 1
return labels
def expand_cluster(data, labels, neighbors, eps, min_samples, cluster):
for neib_index in neighbors:
if labels[neib_index] == -1:
labels[neib_index] = cluster
nerb_nerbs = find_neighbors(data[neib_index,:], eps, data)
if len(nerb_nerbs) >= min_samples:
neighbors.extend(nerb_nerbs)
训练数据:
data = np.loadtxt(r"data\Aggregation.txt") # 导入数据
# 设置参数
eps = 1.5
min_samples = 5
labels = DBscan(data, eps, min_samples)
参数对聚类结果的影响:


我们可以看到,当eps、min_samples的值过大、过小都会对聚类结果造成影响
一种常用的方法是通过可视化数据分布和密度来选择邻域半径。可以绘制数据点的散点图,并根据数据点之间的距离来选择合适的邻域半径。可以尝试不同的邻域半径值,观察聚类结果的质量,选择能够较好地将数据点划分为不同聚类的邻域半径。
其它数据的效果展示
算法改进
尽管DBSCAN算法在密度聚类中具有很多优点,但它也存在一些限制和挑战。下面是一些可能的改进方法,可以进一步提升DBSCAN算法的性能和适用性:
- 自适应邻域半径:传统的DBSCAN算法使用固定的邻域半径来定义邻域范围,这可能对于密度变化较大的数据集不够灵活。改进的方法之一是引入自适应邻域半径,根据数据点的密度变化来调整邻域半径的大小。可以考虑使用局部密度估计方法,例如基于k近邻的方法,来动态地确定每个数据点的邻域半径。
- 高维数据处理:DBSCAN算法在处理高维数据时可能会遇到维度灾难的问题。高维数据中的距离计算变得困难,密度的定义也变得模糊。为了改进DBSCAN在高维数据上的性能,可以考虑使用特征选择或降维技术,将数据映射到更低维度的空间中,以减少维度灾难的影响。
- 基于密度的参数选择:DBSCAN算法的性能非常依赖于邻域半径和最小邻居数目的选择。为了改进算法的鲁棒性,可以考虑基于数据集的密度分布进行参数选择。例如,可以使用统计方法或可视化方法来估计数据点之间的密度分布,从而自动选择合适的邻域半径和最小邻居数目。
- 噪音点处理:DBSCAN算法对于噪音点的处理是通过将其标记为噪音点来实现的。然而,在实际应用中,噪音点可能会对聚类结果产生一定的干扰。为了改进噪音点的处理,可以考虑引入噪音点的权重,或者使用半监督的方法来对噪音点进行更精确的处理。
- 大数据集处理:对于大规模数据集,DBSCAN算法可能会面临存储和计算效率的挑战。为了改进算法的可扩展性,可以考虑使用基于索引的加速技术,如R树或KD树,来提高算法的效率。另外,可以采用分布式计算或增量计算的方法来处理大规模数据集。
这些改进方法只是对DBSCAN算法进行优化的一部分,具体的改进方法取决于应用场景和需求。通过结合领域知识和实际问题的特点,可以选择适合的改进方法来提升DBSCAN算法的性能和适用性。
部分参考 周志华《机器学习》