机器学习实战——密度聚类算法

1 密度聚类

密度聚类假设聚类结构能够通过样本分布的密集程度确定,通常情形下,密度聚类算法从样本密度的角度来考察样本之间的可连接性,并基于可连接样本不断扩展聚类簇以获得最终的聚类结果。
DBSCAN 是一种很典型的密度聚类算法,给定领域参数的半径为 e ,最小样本点为 MinPts 。该算法中几个较重要的概念如下:

  • e 邻域:给定对象半径为 e 内的区域称为该对象的 e 邻域;
  • 核心对象:如果给定对象 e 邻域内的样本点数大于等于 MinPts,则称该对象为核心对象;
  • 边界对象:在半径 e 内点的数量小于 MinPts,但是落在核心点的邻域内。
  • 噪声对象:既不是核心对象也不是边界对象的样本。
  • 直接密度可达:对于样本集合 D,如果样本点 q 在点 p 的 e 邻域内,并且 p 为核心对象,那么对象 q 从对象 p 直接密度可达。
  • 密度可达:对于样本集合 D,给定一串样本点 p1,p2.pnp=p1,q=pnp_1,p_2….p_n,p= p_1,q= p_n,假如对象 pip_ipi1p_{i-1} 直接密度可达,那么对象 q 从对象 p 密度可达。
  • 密度相连:存在样本集合 D 中的一点 k,如果对象 k 到对象 p 和对象 q 都是密度可达的,那么 p 和 q 密度相联。
    以下图为例对上述概念举例说明:
    机器学习实战——密度聚类算法
    DBSCAN 算法的具体流程如下
  • 1 初始化核心对象集合为空集:Ω=Ω=∅
  • 2 寻找核心对象:遍历所有的样本点 xi,i=1,2,...,Nx_i,i=1,2,...,N,计算 Ne(xi)N_e(x_i),如果Ne(xi)MinPts|N_e(x_i)|≥MinPts,则 Ω=Ω{xi}Ω=Ω⋃\{x_i\}
  • 3 迭代:以任一未访问过的核心对象为出发点,找出所有其密度可达的样本生成的聚类簇,直到所有的核心对象都被访问为止。

注意:核心点以内的所有点都与核心点为同一类,所以如果某两个聚类簇集中有一个点为重复,那两个聚类簇应该合并为一类,例如:类别 1:[1,2,4,6,8],类别 2:[3,6,7,9,10,99]。这两个集合最初是两个类别,但是因为有共同点 6,那么他俩应当合并为 1 类。上述算法可以简单的表述为如下形式:
1)求出所有点的距离矩阵 dis=[n,n], n 为训练集的个数。
2)如果 e 取值为 3,那么 dis 的每一行中 >3 的所有点个数的和只要 >MinPts ,则为 1 个类别。
3)所有这些类别进行重复检查,只要有重复值则合并,直到没有重复。
4)这些没有重复的类别就是最终形成的类别。

2 sklearn中的实现

class sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric=’euclidean’, metric_params=None, algorithm=’auto’, leaf_size=30, p=None, n_jobs=None)

主要参数说明

  • eps: 即邻域参数,默认值是 0.5。一般需要多次选择之后确定。eps 过大,则更多的点会落在核心对象的邻域内,聚类的类别数可能会减少,即把本不应该是一类的样本会被划为一类;反之则类别数可能会增大,本来是一类的样本却被划分开。
  • min_samples:样本点要成为核心对象所需要的邻域内样本数阈值。默认值是5,通常和 eps 一起调参。在 eps 一定的情况下,min_samples 过大,则核心对象会过少,此时簇内部分本来是一类的样本可能会被标为噪音点,类别数也会变多,若 min_samples 过小的话,则会产生大量的核心对象,可能会导致类别数过少。
  • metric:最近邻距离度量参数。可以使用的距离度量参数有:欧式距离、曼哈顿距离、切比雪夫距离、闵可夫斯基距离等。默认的是欧式距离。
  • algorithm:最近邻搜索算法参数,用于计算两点间距离并找出最近邻的点。共有 4 种可选输入, brute 是蛮力实现,kd_tree 是 KD 树实现,ball_tree 是球树实现, auto 则会在三种算法中做权衡,选择一个拟合最好的最优算法。一般使用默认的 auto 即可。
  • leaf_size:最近邻搜索算法参数,为使用 KD 树或者球树时, 停止建子树的叶子节点数量的阈值。
  • p: 最近邻距离度量参数。只用于闵可夫斯基距离和带权重闵可夫斯基距离中 p 值的选择,p=1 为曼哈顿距离, p=2 为欧式距离。如果使用默认的欧式距离不需要管这个参数。
# make_moons是月型的数据集
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'] #中文显示问题
plt.rcParams['axes.unicode_minus'] = False #负数显示问题

# 构造数据集 
n_samples = 1500
X,y = make_moons(n_samples=n_samples, noise=.05)

plt.subplot(1,2,1)
plt.scatter(X[:,0],X[:,1],c=y)
plt.title('原始图像')

# 训练对象并调整参数值 
y_predict = DBSCAN(eps=0.2, min_samples=5).fit_predict(X) 

plt.subplot(1,2,2)
plt.scatter(X[:,0],X[:,1],c=y_predict)
plt.title('预测图像')

机器学习实战——密度聚类算法

相关文章: