机器学习|机器学习之聚类算法②——DBSCAN


文章目录

    • DBSCAN基本概念
    • DBSCAN思想
    • DBSCAN密度定义
    • DBSCAN聚类算法
    • DBSCAN小结
    • DBSCAN 优缺点
    • 代码及实现
    • DBSCAN超参数
    • 参考文献

DBSCAN基本概念
  • DBSCAN(Density-Based Spatial Clustering of Applications with Noise -------基于密度的噪声应用空间聚类)是一个比较有代表性的基于密度的聚类算法。与划分和层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在噪声的空间数据库中发现任意形状的聚类。
DBSCAN思想
  • DBSCAN算法将聚类视为由低密度区域分隔的高密度区域。由于这种相当普遍的观点,DBSCAN发现的聚类可以是任何形状,而k-均值假设聚类是凸形的。DBSCAN的核心组件是核心样本的概念,核心样本是高密度区域的样本。因此,簇是一组核心样本,每个核心样本彼此接近(通过一些距离测量)和一组接近核心样本的非核心样本(但它们本身不是核心样本)。有两个参数的算法, min_samples和eps,它正式定义了我们的意思,当我们说密集。更高min_samples或更低eps 表示形成簇所需的更高密度。
  • 我们将核心样本定义为数据集中的样本,使得min_samples在距离内存在其他样本 eps,其被定义为核心样本的邻居。这告诉我们核心样本位于向量空间的密集区域。群集是一组核心样本,可以通过递归取岩芯样品,发现其所有的邻居都岩芯样品,发现所有的构建 自己的邻居是岩心样品,等等。群集还具有一组非核心样本,这些样本是群集中核心样本的邻居,但它们本身不是核心样本。直观地,这些样品位于簇的边缘。
  • 根据定义,任何核心样本都是群集的一部分。任何不是核心样本且至少eps与任何核心样本保持距离的样本都被算法视为异常值。
  • 虽然参数min_samples主要控制算法如何耐受是朝着噪声(在嘈杂和大型数据集可能是desiable增加这个参数),该参数eps是关键的,以适当地选择为所述数据集合和距离函数,并且通常不能在被左默认值。它控制着点的当地邻域。如果选择得太小,大多数数据根本不会聚集(并标记-1为“噪声”)。如果选择得太大,则会导致关闭群集合并到一个群集中,并最终将整个数据集作为单个群集返回。
  • DBSCAN的聚类定义很简单:由密度可达关系导出的最大密度相连的样本集合,即为我们最终聚类的一个类别,或者说一个簇。
  • 这个DBSCAN的簇里面可以有一个或者多个核心对象。如果只有一个核心对象,则簇里其他的非核心对象样本都在这个核心对象的?-邻域里;如果有多个核心对象,则簇里的任意一个核心对象的?-邻域中一定有一个其他的核心对象,否则这两个核心对象无法密度可达。这些核心对象的?-邻域里所有的样本的集合组成的一个DBSCAN聚类簇。
  • 那么怎么才能找到这样的簇样本集合呢?DBSCAN使用的方法很简单,它任意选择一个没有类别的核心对象作为种子,然后找到所有这个核心对象能够密度可达的样本集合,即为一个聚类簇。接着继续选择另一个没有类别的核心对象去寻找密度可达的样本集合,这样就得到另一个聚类簇。一直运行到所有核心对象都有类别为止。
  • 基本上这就是DBSCAN算法的主要内容了,是不是很简单?但是我们还是有三个问题没有考虑。
  • 第一个是一些异常样本点或者说少量游离于簇外的样本点,这些点不在任何一个核心对象在周围,在DBSCAN中,我们一般将这些样本点标记为噪音点。
  • 第二个是距离的度量问题,即如何计算某样本和核心对象样本的距离。在DBSCAN中,一般采用最近邻思想,采用某一种距离度量来衡量样本距离,比如欧式距离。这和KNN分类算法的最近邻思想完全相同。对应少量的样本,寻找最近邻可以直接去计算所有样本的距离,如果样本量较大,则一般采用KD树或者球树来快速的搜索最近邻。如果大家对于最近邻的思想,距离度量,KD树和球树不熟悉,建议参考之前写的另一篇文章K近邻法(KNN)原理小结。
  • 第三种问题比较特殊,某些样本可能到两个核心对象的距离都小于?,但是这两个核心对象由于不是密度直达,又不属于同一个聚类簇,那么如果界定这个样本的类别呢?一般来说,此时DBSCAN采用先来后到,先进行聚类的类别簇会标记这个样本为它的类别。也就是说DBSCAN的算法不是完全稳定的算法。
DBSCAN密度定义 DBSCAN是基于一组邻域来描述样本集的紧密程度的,参数(?, MinPts)用来描述邻域的样本分布紧密程度。其中,?描述了某一样本的邻域距离阈值,MinPts描述了某一样本的距离为?的邻域中样本个数的阈值。
假设我的样本集是 D = ( x 1 , x 2 , . . . , x m ) D=(x_1,x_2,...,x_m) D=(x1?,x2?,...,xm?),则DBSCAN具体的密度描述定义如下:
1) ?-邻域:对于 x j ∈ D x_j∈D xj?∈D,其?-邻域包含样本集D中与 x j x_j xj?的距离不大于?的子样本集,即 N ? ( x j ) = x i ∈ D ∣ d i s t a n c e ( x i , x j ) ≤ ? N?(x_j)={x_i∈D|distance(x_i,x_j)≤?} N?(xj?)=xi?∈D∣distance(xi?,xj?)≤?, 这个子样本集的个数记为 ∣ N ? ( x j ) ∣ |N?(x_j)| ∣N?(xj?)∣
2)核心对象:对于任一样本 x j ∈ D x_j∈D xj?∈D,如果其?-邻域对应的 N ? ( x j ) N?(x_j) N?(xj?)至少包含MinPts个样本,即如果 ∣ N ? ( x j ) ∣ ≥ M i n P t s |N?(x_j)|≥MinPts ∣N?(xj?)∣≥MinPts,则 x j x_j xj?是核心对象。
3)密度直达:如果 x i x_i xi?位于 x j x_j xj?的?-邻域中,且 x j x_j xj?是核心对象,则称 x i x_i xi?由 x j x_j xj?密度直达。注意反之不一定成立,即此时不能说 x j x_j xj?由 x i x_i xi?密度直达, 除非且xi也是核心对象。
4)密度可达:对于 x i 和 x j x_i和x_j xi?和xj?,如果存在样本样本序列 p 1 , p 2 , . . . , p T p_1,p_2,...,p_{T} p1?,p2?,...,pT?,满足 p 1 = x i , p T = x j p_1=x_i,p_T=x_j p1?=xi?,pT?=xj?, 且 p t + 1 p_{t+1} pt+1?由 p t p_t pt?密度直达,则称 x j 由 x i x_j由x_i xj?由xi?密度可达。也就是说,密度可达满足传递性。此时序列中的传递样本 p 1 , p 2 , . . . , p T ? 1 p_1,p_2,...,p_{T?1} p1?,p2?,...,pT?1?均为核心对象,因为只有核心对象才能使其他样本密度直达。注意密度可达也不满足对称性,这个可以由密度直达的不对称性得出。
5)密度相连:对于 x i 和 x j x_i和x_j xi?和xj?,如果存在核心对象样本 x k , 使 x i 和 x j x_k,使x_i和x_j xk?,使xi?和xj?均由 x k x_k xk?密度可达,则称 x i 和 x j x_i和x_j xi?和xj?密度相连。注意密度相连关系是满足对称性的。
从下图可以很容易看出理解上述定义,图中MinPts=5,红色的点都是核心对象,因为其?-邻域至少有5个样本。黑色的样本是非核心对象。所有核心对象密度直达的样本在以红色核心对象为中心的超球体内,如果不在超球体内,则不能密度直达。图中用绿色箭头连起来的核心对象组成了密度可达的样本序列。在这些密度可达的样本序列的?-邻域内所有的样本相互都是密度相连的。
机器学习|机器学习之聚类算法②——DBSCAN
文章图片

DBSCAN聚类算法 输入:样本集 D = ( x 1 , x 2 , . . . , x m ) D=(x_1,x_2,...,x_m) D=(x1?,x2?,...,xm?),邻域参数(?,MinPts), 样本距离度量方式
输出: 簇划分C.
1)初始化核心对象集合Ω=?, 初始化聚类簇数k=0,初始化未访问样本集合Γ = D, 簇划分C = ?

2) 对于j=1,2,…m, 按下面的步骤找出所有的核心对象:
  • a) 通过距离度量方式,找到样本 x j x_j xj?的?-邻域子样本集 N ? ( x j ) N?(x_j) N?(xj?)
  • b) 如果子样本集样本个数满足 ∣ N ? ( x j ) ∣ ≥ M i n P t s |N?(x_j)|≥MinPts ∣N?(xj?)∣≥MinPts, 将样本 x j x_j xj?加入核心对象样本集合: Ω = Ω ∪ x j Ω=Ω∪{x_j} Ω=Ω∪xj?
3) 如果核心对象集合Ω=?,则算法结束,否则转入步骤4.
4) 在核心对象集合Ω中,随机选择一个核心对象o,初始化当前簇核心对象队列 Ω c u r = o Ω_{cur}={o} Ωcur?=o, 初始化类别序号k=k+1,初始化当前簇样本集合 C k = o , C_k={o}, Ck?=o, 更新未访问样本集合Γ=Γ?{o}
5)如果当前簇核心对象队列 Ω c u r ? Ω_{cur}? Ωcur??,则当前聚类簇 C k C_k Ck?生成完毕, 更新簇划分C= C 1 , C 2 , . . . , C k {C_1,C_2,...,C_k} C1?,C2?,...,Ck?, 更新核心对象集合 Ω = Ω ? C k Ω=Ω?C_k Ω=Ω?Ck?, 转入步骤3。
6)在当前簇核心对象队列 Ω c u r Ω_{cur} Ωcur?中取出一个核心对象o′,通过邻域距离阈值?找出所有的?-邻域子样本集N?(o′),令 Δ = N ? ( o ′ ) ∩ Γ , Δ=N?(o′)∩Γ, Δ=N?(o′)∩Γ, 更新当前簇样本集合 C k = C k ∪ Δ C_k=C_k∪Δ Ck?=Ck?∪Δ, 更新未访问样本集合Γ=Γ?Δ, 更新 Ω c u r = Ω c u r ∪ ( Δ ∩ Ω ) ? o ′ Ω_{cur}=Ω_{cur}∪(Δ∩Ω)?o′ Ωcur?=Ωcur?∪(Δ∩Ω)?o′,转入步骤5.
输出结果为: 簇划分 C = C 1 , C 2 , . . . , C k C={C_1,C_2,...,C_k} C=C1?,C2?,...,Ck?
DBSCAN小结
  • 和传统的K-Means算法相比,DBSCAN最大的不同就是不需要输入类别数k,当然它最大的优势是可以发现任意形状的聚类簇,而不是像K-Means,一般仅仅使用于凸的样本集聚类。同时它在聚类的同时还可以找出异常点,这点和BIRCH算法类似。
  • 那么我们什么时候需要用DBSCAN来聚类呢?一般来说,如果数据集是稠密的,并且数据集不是凸的,那么用DBSCAN会比K-Means聚类效果好很多。如果数据集不是稠密的,则不推荐用DBSCAN来聚类。
DBSCAN 优缺点 DBSCAN的主要优点有:
1) 可以对任意形状的稠密数据集进行聚类,相对的,K-Means之类的聚类算法一般只适用于凸数据集。
2) 可以在聚类的同时发现异常点,对数据集中的异常点不敏感。
3) 聚类结果没有偏倚,相对的,K-Means之类的聚类算法初始值对聚类结果有很大影响。
DBSCAN的主要缺点有:
1)如果样本集的密度不均匀、聚类间距差相差很大时,聚类质量较差,这时用DBSCAN聚类一般不适合。
2) 如果样本集较大时,聚类收敛时间较长,此时可以对搜索最近邻时建立的KD树或者球树进行规模限制来改进。
3) 调参相对于传统的K-Means之类的聚类算法稍复杂,主要需要对距离阈值?,邻域样本数阈值MinPts联合调参,不同的参数组合对最后的聚类效果有较大影响。
代码及实现
import numpy as np import matplotlib.pyplot as plt from sklearn import datasetsX1, y1=datasets.make_circles(n_samples=5000, factor=.6,noise=.05) X2, y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],random_state=9)X = np.concatenate((X1, X2)) plt.scatter(X[:, 0], X[:, 1], marker='o') plt.show()from sklearn.cluster import KMeans y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()from sklearn.cluster import DBSCAN y_pred = DBSCAN().fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()y_pred = DBSCAN(eps = 0.1).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()

效果展示
机器学习|机器学习之聚类算法②——DBSCAN
文章图片
机器学习|机器学习之聚类算法②——DBSCAN
文章图片

机器学习|机器学习之聚类算法②——DBSCAN
文章图片
机器学习|机器学习之聚类算法②——DBSCAN
文章图片

DBSCAN超参数 sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric=’euclidean’, metric_params=None, algorithm=’auto’, leaf_size=30, p=None, n_jobs=None)
从矢量数组或距离矩阵执行DBSCAN聚类。
DBSCAN - 基于密度的噪声应用空间聚类。查找高密度的核心样本并从中扩展聚类。适用于包含相似密度簇的数据。
参数
  • eps : float,optional
    两个样本之间的最大距离,一个被认为是另一个样本的邻域。这不是群集中点的距离的最大界限。这是为您的数据集和距离函数选择适当的最重要的DBSCAN参数。
  • min_samples : int,optional
    对于要被视为核心点的点,邻域中的样本数(或总权重)。这包括点本身。
  • metric : string或callable
    计算要素数组中实例之间距离时使用的度量标准。如果metric是字符串或可调用的,则它必须是sklearn.metrics.pairwise_distances其metric metric参数允许的选项之一。如果度量是“预先计算的”,则假定X是距离矩阵,并且必须是正方形。X可以是稀疏矩阵,在这种情况下,只有“非零”元素可以被认为是DBSCAN的邻居。
    版本0.17中的新功能:度量预先计算以接受预先计算的稀疏矩阵。
  • metric_params : dict,optional
    度量函数的其他关键字参数。
  • algorithm : {‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},optional
    NearestNeighbors模块用于计算逐点距离并找到最近邻居的算法。有关详细信息,请参阅NearestNeighbors模块文档。
  • leaf_size : int,optional(default= 30)
    叶子大小传递给BallTree或cKDTree。这可能会影响构造和查询的速度,以及存储树所需的内存。最佳值取决于问题的性质。
  • p : float,optional
    用于计算点之间距离的Minkowski度量的功效。
  • n_jobs : int或None,可选(default=None)
    要运行的并行作业数。 None除非在joblib.parallel_backend上下文中,否则表示1 。 -1表示使用所有处理器
属性
  • core_sample_indices_ : array,shape = [n_core_samples]
    核心样本指数。
  • components_ : array,shape = [n_core_samples,n_features]
    通过培训找到的每个核心样本的副本。
  • labels_ : array,shape = [n_samples]
    给予fit()的数据集中每个点的聚类标签。噪声样本的标签为-1。
【机器学习|机器学习之聚类算法②——DBSCAN】方法
  • fit(self,X [,y,sample_weight]) ---------------------从要素或距离矩阵执行DBSCAN聚类。
  • fit_predict(self,X [,y,sample_weight]) -----------在X上执行群集并返回群集标签。
  • get_params(self[,deep]) -------------------------------获取此估算工具的参数。
  • set_params(self,\ * \ * params)--------------------------设置此估算器的参数。
参考文献
  • https://www.cnblogs.com/pinard/p/6208966.html
  • https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html#sklearn.cluster.DBSCAN

    推荐阅读