Fork me on GitHub

scikit-learn聚类---机器学习算法之DBSCAN算法

DBSCAN聚类算法

  • 基于密度的空间聚类算法,该算法将具有足够密度的区域划分为簇,并在具有噪声的空间数据中发现任意形状的簇,它将簇定义为密度相连的点的最大集合。

  • DBSCAN算法需要规定两个参数

    • epsilon:在一个点周围邻近区域半径

    • minPts:邻近区域内至少包含点个数

      根据以上两个参数结合epsilon-neighborhood的特征把样本中点分为三类

      • 核心点(cor point):满足NBHD(p,epsilon) >= minPts,则为样本点
      • 边界点(border point)NBHD(p,epsilon) < minPts,但是该点可由一些核点获得
      • 离群点(Outlier):既不是核点也不是边缘点
  • 如果不能理解可以看如下图,分布样本空间的众多样本,我们将样本空间中距离相近的聚成一类,A点附近点密度较大,红色的圆圈根据规范(epsilon邻近区域半径),最终收纳A附近的5个点,标记为红色就是,标记为红色定位同一个簇,其他没有被收纳的根据一样规则成簇。(形象来说,我们可以认为这是系统在众多样本点钟获取选中一个,围绕这个被选中的样本点画一个圆,规定这个圆的半径以及圆内最少包含的样本点,如果在指定半径内足够多的样本点在内,那么这个圆圈的圆心就转移到这个内部样本其他点,继续去圈附近其他的样本点,类似于传销一样,继续去发展下线,等到这个滚来滚去的圆发现所圈住的样本点的数量少于预先指定的值,就停止了。那么我们称最开始那个点为核心点。如下图A,停下来那个点为边界点,如下图B,C。没有滚的那个点为离群点,如下图N)

1.1DBSCAN与K-Means聚类算法的区别

  • 因为K-Means聚类算法只能处理球形的簇,也就是一个聚成实心团,但往往现实中数据形状各有不同,这个时候,传统聚类算法就不行了,于是你可以通过密度。就是DBSCAN聚类算法

1.2DBSCAN步骤(在已知epsilon和minPts的前提下)

  • 任意选择一个点(既没有指定到一个类也没有特定为离群点),计算它NBHD(p,epsilon)判断是否为核点,如果是,在该点周围建立一个类,否则,设定为离群点。
  • 遍历其他点,直到建立一个类,把directly-reachable的点加入类中,接着把density-reachable的点也加进来,如果标记为离群的点被加进来,会修改状态为边界点。
  • 重复步骤1和2,直到所有的点满足在类中(核点或边缘点)或者为边界点

1.3DBSCAN类重要参数

DBSCAN类的重要参数也分为两类,一类是DBSCAN算法本身的参数,一类是最近邻度量的参数,下面我们对这些参数做一个总结。

    1)eps: DBSCAN算法参数,即我们的ϵϵ-邻域的距离阈值,和样本距离超过ϵϵ的样本点不在ϵϵ-邻域内。默认值是0.5.一般需要通过在多组值里面选择一个合适的阈值。eps过大,则更多的点会落在核心对象的ϵϵ-邻域,此时我们的类别数可能会减少, 本来不应该是一类的样本也会被划为一类。反之则类别数可能会增大,本来是一类的样本却被划分开。

    2)min_samples: DBSCAN算法参数,即样本点要成为核心对象所需要的ϵϵ-邻域的样本数阈值。默认值是5. 一般需要通过在多组值里面选择一个合适的阈值。通常和eps一起调参。在eps一定的情况下,min_samples过大,则核心对象会过少,此时簇内部分本来是一类的样本可能会被标为噪音点,类别数也会变多。反之min_samples过小的话,则会产生大量的核心对象,可能会导致类别数过少。

    3)metric:最近邻距离度量参数。可以使用的距离度量较多,一般来说DBSCAN使用默认的欧式距离(即p=2的闵可夫斯基距离)就可以满足我们的需求。可以使用的距离度量参数有:

  

    4)algorithm:最近邻搜索算法参数,算法一共有三种,第一种是蛮力实现,第二种是KD树实现,第三种是球树实现。这三种方法在K近邻法(KNN)原理小结中都有讲述,如果不熟悉可以去复习下。对于这个参数,一共有4种可选输入,‘brute’对应第一种蛮力实现,‘kd_tree’对应第二种KD树实现,‘ball_tree’对应第三种的球树实现, ‘auto’则会在上面三种算法中做权衡,选择一个拟合最好的最优算法。需要注意的是,如果输入样本特征是稀疏的时候,无论我们选择哪种算法,最后scikit-learn都会去用蛮力实现‘brute’。个人的经验,一般情况使用默认的 ‘auto’就够了。 如果数据量很大或者特征也很多,用"auto"建树时间可能会很长,效率不高,建议选择KD树实现‘kd_tree’,此时如果发现‘kd_tree’速度比较慢或者已经知道样本分布不是很均匀时,可以尝试用‘ball_tree’。而如果输入样本是稀疏的,无论你选择哪个算法最后实际运行的都是‘brute’。

    5)leaf_size:最近邻搜索算法参数,为使用KD树或者球树时, 停止建子树的叶子节点数量的阈值。这个值越小,则生成的KD树或者球树就越大,层数越深,建树时间越长,反之,则生成的KD树或者球树会小,层数较浅,建树时间较短。默认是30. 因为这个值一般只影响算法的运行速度和使用内存大小,因此一般情况下可以不管它。

    6) p: 最近邻距离度量参数。只用于闵可夫斯基距离和带权重闵可夫斯基距离中p值的选择,p=1为曼哈顿距离, p=2为欧式距离。如果使用默认的欧式距离不需要管这个参数。

    以上就是DBSCAN类的主要参数介绍,其实需要调参的就是两个参数eps和min_samples,这两个值的组合对最终的聚类效果有很大的影响。

1.4代码示例:

  • 为体现DBSCAN在非凸数据的聚类优点,首先生成一组随机数据:

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    %matplotlib inline
    
    X1,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))
    
  • K-Means聚类效果,代码如下

    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()
    

  • DBSCAN聚类效果,代码如下:

    from sklearn.cluster import DBSCAN
    y_pred = DBSCAN().fit_predict(X)
    plt.scatter(X[:,0],X[:,1],c=y_pred)
    plt.show()
    

  • 但不是我们所期望的,它将所有数据都归为一类,需要对DBSCAN的两个关键参数eps和min_samples进行调参,我们减少eps到0.1看看效果:

    from sklearn.cluster import DBSCAN
    y_pred = DBSCAN(eps=0.1).fit_predict(X)
    plt.scatter(X[:,0],X[:,1],c=y_pred)
    plt.show()
    

参照链接:

posted @ 2019-12-29 14:58  是阿凯啊  阅读(996)  评论(0编辑  收藏  举报