聚类分析|基于密度的聚类方法DBSCAN及其Python实现

0. 基于密度的聚类方法

之前介绍过基于划分的聚类算法,如k-means和k-medoids,也介绍过基于层次聚类的方法。这两种方法本质上都是基于距离的算法,只能发现类圆形的聚类。

基于密度的方法(Density-based Methods)是基于密度的,可以克服基于距离的算法只能发现“类圆形”聚类的缺点。
主要思想:只要在给定半径邻近区域的密度超过某个阈值,就把它添加到与之相近的簇类中去。
这样的方法可以用来过滤噪声数据,并且可以发现任意形状的聚类。
基于密度的方法中,代表算法有:

  • DBSCAN算法
  • OPTICS算法
  • DENCLUE算法
    以下对DBSCAN(Density Based Spatial Clustering of Applications with Noise,DBSCAN)聚类算法进行介绍。

1. DBSCAN聚类算法的相关概念

DBSCAN是基于密度聚类中的经典算法,突出特色在于:

  • 第一,利用小类的密度可达性(或称连通性),可发现任意形状的小类
  • 第二,聚类同时可以发现数据中的噪声,也即离群点

DBSCAN聚类中有两个重要参数:

  1. 邻域半径 ε \varepsilon ε
  2. 邻域半径 ε \varepsilon ε范围内包含的最少观测点个数,记为 m i n P t s minPts minPts

基于这两个参数,DBSCAN聚类将样本观测点分成以下4类:

  1. 核心点(核心样本) P P P:若任意样本观测点 O O O的邻域半径 ε \varepsilon ε内的邻居个数不少于 m i n P t s minPts minPts,则称 O O O为核心点,记作 P P P
  2. 核心点 P P P的直接密度可达点 Q Q Q:若任意样本观测点 Q Q Q在核心点 P P P的邻域半径 ε \varepsilon ε范围内,则称点 Q Q Q为核心点 P P P的直接密度可达点。也称从点 P P P直接密度可达点 Q Q Q
  3. 核心点 P P P的密度可达点 Q Q Q:若存在一系列样本观测点 O 1 , O 2 , … , O n O_1, O_2, …, O_n O1,O2,,On,且 O i + 1 ( i = 1 , 2 , . . . , n − 1 ) O_{i+1}(i=1,2,...,n-1) Oi+1(i=1,2,...,n1) O i O_i Oi的直接密度可达点,且 O i = P , O n = Q O_i=P,O_n=Q Oi=P,On=Q,则称 Q Q Q是点 P P P的密度可达点,也称从点 P P P密度可达点 Q Q Q
  4. 噪声点:除上述类型之外的样本观测点,均定义为噪声点。
    如下图所示, q q q是一个核心样本, p p p q q q直接密度可达。
    在这里插入图片描述
  • 直接密度可达的传递性会导致密度可达!
  • 若存在任意样本观测点 O O O,同时密度可达点 O 1 O_1 O1和点 O 2 O_2 O2,则称点 O 1 O_1 O1和点 O 2 O_2 O2密度相连的。

2. DBSCAN聚类过程

设置邻域半径 ε \varepsilon ε和邻域半径 ε \varepsilon ε范围内包含的最少观测点个数 m i n P t s minPts minPts
在参数设定的条件下,DBSCAN聚类过程大致包括形成小类和合并小类两个阶段:

2.1 形成小类

  1. 从任意一个样本观测点 O i O_i Oi开始,在参数限定的条件下判断 O i O_i Oi是否为核心点。
  2. O i O_i Oi是核心点,首先标记该点为核心点。然后,找到 O i O_i Oi的所有(如 m m m个)直接密度可达点(包括边缘点),并形成一个以 O i O_i Oi为“核心”的小类,记作 C i C_i Ci m m m个直接密度可达点(尚无小类标签)和样本观测点 O i O_i Oi的小类标签均为 C i C_i Ci
  3. O i O_i Oi不是核心点,那么 O i O_i Oi可能是其他核心点的直接密度可达点,或密度可达点,亦或噪声点。若 O i O_i Oi是直接密度可达点或密度可达点,则一定会在后续的处理中被归到某个小类,带有小类标签 C j C_j Cj。若是噪声点,则不会被归到任何小类中,始终不带有小类标签

2.2 合并小类

  • 判断带有核心点标签的所有核心点之间,是否存在密度可达和密度相连关系。若存在,则将相应的小类合并起来,并修改相应样本观测点的小类标签

3. DBSCAN算法的Python实现

在scikit-learn中,包含sklearn.cluster.DBSCAN的算法。DBSCAN()常用形式为:

DBSCAN(eps=0.5,min_samples=5,metric=’euclidean’, algorithm=’auto’)

参数说明:

  1. eps:设置半径,用以确定邻域的大小,默认0.5。
  2. min_samples:int,设置阈值MinPts。
  3. metric:采用的距离计算方式,默认是欧式距离。
  4. algorithm:取值{’auto’,’ball_tree’,’kd_tree’,’brute’}。用于计算两点间距离并找出最近邻的点。取值为:’auto’:由算法自动取舍合适的算法;’ball_tree’:用ball树来搜索;’kd_tree’:用kd树搜索;’brute’:暴力搜索。对于稀疏数据,一般取值’brute’。

3.1 DBSCAN算法示例

  1. 首先生成一组随机数据,为了体现DBSCAN在非凸数据的聚类优点,生成三簇数据,两组是非凸的。
  2. 直接使用DBSCAN默认参数,观看聚类效果
  3. 对DBSCAN的两个关键的参数eps和min_samples进行调参,当类别数太少,需要增加类别数,那么就可以减少邻域的大小,默认是0.5,下面减到0.1
  4. 将min_samples从默认的5增加到10,观看效果。
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
x1,y1=datasets.make_circles(n_samples=5000, factor=0.6,noise=0.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.rcParams['font.sans-serif']=['SimHei'] 
plt.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(10,8))
plt.subplot(2,2,1)
# 观察总体样本分布
plt.title("整体样本分布")
plt.scatter(x[:,0],x[:,1], marker='o')
plt.subplot(2,2,2)
# 观察认参数聚类效果
plt.title("默认参数聚类效果")
x = np.concatenate((x1, x2))
y_pred = DBSCAN().fit_predict(x)
plt.scatter(x[:,0],x[:, 1], c=y_pred)
plt.subplot(2,2,3)
# 观察邻域为0.1时聚类效果
plt.title("邻域为0.1时聚类效果")
y_pred2 = DBSCAN(eps = 0.1).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred2)
plt.subplot(2,2,4)
# 观察minPts为10时聚类效果
plt.title("minPts为0.1时聚类效果")
y_pred3 = DBSCAN(eps = 0.1,min_samples =10).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred3)
plt.show()

在这里插入图片描述

3.2 DBSCAN的异型聚类特点

DBSCAN聚类的最大特点是能够发现任意形状的类。
DBSCAN算法对参数 ε \varepsilon ε(邻域半径)和 m i n P t s minPts minPts极为敏感。以下进行相关参数设置试验以说明特性:

  1. 邻域半径 ε \varepsilon ε较小,且邻域范围内的最少观测点个数 m i n P t s minPts minPts较多
  2. 邻域半径 ε \varepsilon ε较大,且邻域范围内的最少观测点个数 m i n P t s minPts minPts较少
  3. 适中的参数设置

试验代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from itertools import cycle
import warnings
warnings.filterwarnings(action = 'ignore')
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']  
plt.rcParams['axes.unicode_minus']=False
from scipy.stats import norm
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN,Birch,KMeans,estimate_bandwidth,MeanShift
X=pd.read_csv('异形聚类数据.txt',header=0)
fig=plt.figure(figsize=(15,10))
plt.subplot(231)
plt.scatter(X['x1'],X['x2'])
plt.title("异形样本观测的分布(样本量=%d)"%len(X))
plt.xlabel("X1")
plt.ylabel("X2")

colors = 'bgrcmyk'
EPS=[0.2,0.5,0.2,0.5,0.2]
MinS=[200,80,100,300,30]
Gid=1
for eps,mins in zip(EPS,MinS):
    DBS=DBSCAN(min_samples=mins,eps=eps)
    DBS.fit(X)
    labels=np.unique(DBS.labels_)
    Gid+=1
    plt.subplot(2,3,Gid)
    for i,k in enumerate(labels):
        if k==-1:  #噪声点
            c='darkorange'
            m='*'
        else:
            c=colors[i]
            m='o'
        plt.scatter(X.iloc[DBS.labels_==k,0],X.iloc[DBS.labels_==k,1],c=c,s=30,alpha=0.8,marker=m)
    
    plt.title("DBSCAN聚类解\n(最少观测点=%d,近邻半径=%.2f)\n (%d个核心点,%d个噪声点,%d个其他点)"%(mins,eps,len(DBS.components_),
                                                        sum(DBS.labels_==-1),len(X)-len(DBS.components_)-sum(DBS.labels_==-1)))
    plt.xlabel("X1")
    plt.ylabel("X2")
fig.subplots_adjust(hspace=0.3)
fig.subplots_adjust(wspace=0.2)

在这里插入图片描述

4. DBSCAN算法的缺点

在DBSCAN算法中,有两个初始参数 ε \varepsilon ε(邻域半径)和 m i n P t s minPts minPts ε \varepsilon ε邻域最小样本数)需要用户手动设置输入,并且聚类的类簇结果对这两个参数的取值非常敏感,不同的取值将产生不同的聚类结果,其实这也是大多数需要初始化参数聚类算法的弊端。

  • 33
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
DBSCAN是一种基于密度聚类算法,可以用于发现任意形状的簇。它的核心思想是将密度相连的样本点划分为一个簇,并且可以识别噪声点。下面是使用Python实现DBSCAN聚类分析的步骤: 1. 导入需要的库和数据集 ```python import numpy as np from sklearn.cluster import DBSCAN from sklearn.datasets import make_blobs import matplotlib.pyplot as plt # 生成样本数据,共1000个点,4个中心点,标准差为0.5 X, y = make_blobs(n_samples=1000, centers=4, cluster_std=0.5, random_state=0) ``` 2. 设置DBSCAN参数,并进行聚类分析 ```python dbscan = DBSCAN(eps=0.5, min_samples=5) # eps为邻域半径,min_samples为邻域内最少样本数 dbscan.fit(X) ``` 3. 可视化聚类结果 ```python # 可视化结果 plt.scatter(X[:, 0], X[:, 1], c=dbscan.labels_, cmap='rainbow') plt.title('DBSCAN Clustering') plt.show() ``` 完整代码如下: ```python import numpy as np from sklearn.cluster import DBSCAN from sklearn.datasets import make_blobs import matplotlib.pyplot as plt # 生成样本数据,共1000个点,4个中心点,标准差为0.5 X, y = make_blobs(n_samples=1000, centers=4, cluster_std=0.5, random_state=0) # 设置DBSCAN参数,并进行聚类分析 dbscan = DBSCAN(eps=0.5, min_samples=5) # eps为邻域半径,min_samples为邻域内最少样本数 dbscan.fit(X) # 可视化结果 plt.scatter(X[:, 0], X[:, 1], c=dbscan.labels_, cmap='rainbow') plt.title('DBSCAN Clustering') plt.show() ``` 运行代码后,会得到一个可视化的聚类结果图。可以看出,DBSCAN算法成功地将数据集分为了4个簇,并将噪声点标记为-1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皖山文武

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值