机器学习8—聚类算法之DBSCAN和Birch算法

本文深入解析DBSCAN与Birch两种聚类算法的特点与应用。DBSCAN算法无需预先设定聚类数量,能有效处理噪声点及任意形状的聚类问题;Birch算法适用于大规模数据集,通过聚类特征树提高聚类速度和质量。文章通过实例演示了两种算法的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、基于密度的聚类DBSCAN算法

DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种基于密度的空间聚类算法。 该算法将具有足够密度的区域划分为簇,并在具有噪声的空间数据库中发现任意形状的簇,它将簇定义为密度相连的点的最大集合。

动画讲解DBSCAN算法的国外网站https://www.naftaliharris.com/blog/visualizing-dbscan-clustering/

1.1DBSCAN算法的基本概念

1.取半径为3,MinPts为3(圆圈能够圈住的最小的数目),则可以得到如下的分类结果,其中,P9为噪音点,P10为噪音点。
在这里插入图片描述

  • MinPts:这个参数就是圆能够圈住的点的个数,也相当于是一个密度,一般这个值都是偏小一些,然后进行多次尝试

  • (1)Eps邻域:给定对象半径Eps内的邻域称为该对象的Eps邻域。

  • (2)核心点(core point):如果对象的Eps邻域至少包含最小数目MinPts的对象,则称该对象为核心对象。

  • (3)边界点(edge point):边界点不是核心点,但落在某个核心点的邻域内。

  • (4)噪音点(outlier point):既不是核心点,也不是边界点的任何点。6,

  • 我们假设最小样本容量为6,A、B、C为核心对象:
    在这里插入图片描述

  • (5) 直接密度可达:给定一个对象集合D,如果p在q的Eps邻域内,而q是一个核心对象,则称对象p从对象q出发时是直接密度可达的,比如 上图中的 A 和 B 、B 和 C 等。

  • (6)密度可达: 如果有一系列的点,都满足上一个点到这个点是密度直达,那么这个系列中不相邻的点就称为密度可达,比如 A 和 D。

  • (7)密度相连: 如果存在对象O∈D,使对象p和q都是从O关于Eps和MinPts密度可达的,那么对象p到q是关于Eps和MinPts密度相连的,比如这 里的 E 和 F 点就是密度相连。

1.2DBSCAN算法参数选择

半径: 半径是最难指定的 ,大了,圈住的点就多了,簇的个数就少了;反之,圈住的点少了,簇的个数就多了,这对我们最后的结果是有影响的。我们这个时候K距离可以帮助我们来设定半径r,也就是要找到突变点,比如:
在这里插入图片描述

1.3DBSCAN算法原理

  • (1)DBSCAN通过检查数据集中每点的Eps邻域来搜索簇,如果点p的Eps邻域包含的点多于MinPts个,则创建一个以p为核心对象的簇;
  • (2)然后,DBSCAN迭代地聚集从这些核心对象直接密度可达的对象,这个过程可能涉及一些密度可达簇的合并;
  • (3)当没有新的点添加到任何簇时,该过程结束。

DBSCAN 算法的簇里面可以有一个或者多个核心点。如果只有一个核心点,则簇里其他的非核心点样本都在这个核心点的 Eps 邻域里。如果有多个核心点,则簇里的任意一个核心点的 Eps 邻域中一定有一个其他的核心点,否则这两个核心点无法密度可达。这些核心点的 Eps 邻域里所有的样本的集合组成一个 DBSCAN 聚类簇。

DBSCAN算法的描述如下。

输入:数据集,邻域半径 Eps,邻域中数据对象数目阈值 MinPts;
输出:密度联通簇。
处理流程如下。

  • 1)从数据集中任意选取一个数据对象点 p;
  • 2)如果对于参数 Eps 和 MinPts,所选取的数据对象点 p 为核心点,则找出所有从 p 密度可达的数据对象点,形成一个簇;
  • 3)如果选取的数据对象点 p 是边缘点,选取另一个数据对象点;
  • 4)重复(2)、(3)步,直到所有点被处理。

DBSCAN 算法的计算复杂的度为 O(n²),n 为数据对象的数目。这种算法对于输入参数 Eps 和 MinPts 是敏感的。

1.4DBSCAN算法中dbscan()函数的说明

dbscan(X, eps=0.5, *, min_samples=5, metric='minkowski',
       metric_params=None, algorithm='auto', leaf_size=30,
       p=2, sample_weight=None, n_jobs=None)

参数说明:

  • eps : float, optional
    两个样本之间的最大距离,一个被认为是另一个样本的邻域。这不是群集中点的距离的最大界限。这是为您的数据集和距离函数选择适当的最重要的DBSCAN参数。

  • min_samples : int,可选
    对于要被视为核心对象的点,邻域中的样本数(或总权重)。这包括点本身。

  • metric:最近邻距离度量参数。默认的欧式距离(即p=2的闵可夫斯基距离),可以使用的距离度量参数有:欧式距离 “euclidean”,曼哈顿距离 “manhattan”,切比雪夫距离“chebyshev”,闵可夫斯基距离 “minkowski”,带权重闵可夫斯基距离 “wminkowski”,标准化欧式距离 “seuclidean”,马氏距离“mahalanobis”。

  • metric_params : dict, optional
    度量函数的其他关键字参数。

  • algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选
    NearestNeighbors模块用于计算逐点距离并找到最近邻居的算法。有关详细信息,请参阅NearestNeighbors模块文档。

  • leaf_size : int,optional(默认值= 30)
    叶子大小传递给BallTree或cKDTree。这可能会影响构造和查询的速度,以及存储树所需的内存。最佳值取决于问题的性质。

  • p : float,可选
    正确译法:用于计算点之间距离的Minkowski矩阵的幂。

  • n_jobs : int或None,可选(默认=无)
    要运行的并行作业数。 None除非在joblib.parallel_backend上下文中,否则表示1 。 -1表示使用所有处理器。

1.5DBSCAN算法的实现

import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.cluster import dbscan

#  make_moons 这个方法是生成两个交错的半圆环
data,_ = datasets.make_moons(500,noise = 0.1,random_state=1)   # 创建数据集
# print('数据集0,1', data)
df = pd.DataFrame(data,columns = ['feature1','feature2'])     # 将数据集转换为dataframe
# 可视化处理
# 绘制样本点,s为样本点大小,aplha为透明度,设置图形名称
# 看下面第1个图
df.plot.scatter('feature1','feature2'
BIRCH(Balanced Iterative Reducing and Clustering using Hierarchies)天生就是为处理超大规模(至少要让你的内存容不下)的数据集而设计的,它可以在任何给定的内存下运行。关于BIRCH的更多特点先不介绍,我先讲一下算法的完整实现细节,对算法的实现过程搞清楚后再去看别人对该算法的评价才会感受深刻。 你不需要具备B树的相关知识,我接下来会讲得很清楚。 BIRCH算法的过程就是要把待分类的数据插入一棵树中,并且原始数据都在叶子节点上。这棵树看起来是这个样子: 在这棵树中有3种类型的节点:Nonleaf、Leaf、MinCluster,Root可能是一种Nonleaf,也可能是一种Leaf。所有的Leaf放入一个双向链表中。每一个节点都包含一个CF值,CF是一个三元组,其中data point instance的个数,是与数据点同维度的向量,是线性,是平方。比如有一个MinCluster里包含3个数据点(1,2,3),(4,5,6),(7,8,9),则 N=3, =(1+4+7,2+5+8,3+6+9)=(12,15,18), =(1+16+49,4+25+64,9+36+81)。 就拿这个MinCluster为例,我们可以计算它的 簇中心 簇半径 簇直径 我们还可以计算两个簇之间的距离,当然你也可以使用D0,D1,D3等等,不过在这里我们使用D2。 有意思的是簇中心、簇半径、簇直径以及两簇之间的距离D0到D3都可以由CF来计算,比如 簇直径 簇间距离,这里的N,LSSS是指两簇合并后大簇的N,LSSS。所谓两簇合并只需要两个对应的CF相加那可 CF1 + CF2 = (N1 + N2 , LS1 + LS2, SS1 + SS2) 每个节点的CF值就是其所有孩子节点CF值之,以每个节点为根节点的子树都可以看成 是一个簇。 Nonleaf、Leaf、MinCluster都是有大小限制的,Nonleaf的孩子节点不能超过B个,Leaf最多只能有L个MinCluster,而一个MinCluster的直径不能超过T。 算法起初,我们扫描数据库,拿到第一个data point instance--(1,2,3),我们创建一个空的LeafMinCluster,把点(1,2,3)的id值放入Mincluster,更新MinCluster的CF值为(1,(1,2,3),(1,4,9)),把MinCluster作为Leaf的一个孩子,更新Leaf的CF值为(1,(1,2,3),(1,4,9))。实际上只要往树中放入一个CF(这里我们用CF作为Nonleaf、Leaf、MinCluster的统称),就要更新从Root到该叶子节点的路径上所有节点的CF值。 当又有一个数据点要插入树中时,把这个点封装为一个MinCluster(这样它就有了一个CF值),把新到的数据点记为CF_new,我们拿到树的根节点的各个孩子节点的CF值,根据D2来找到CF_new与哪个节点最近,就把CF_new加入那个子树上面去。这是一个递归的过程。递归的终止点是要把CF_new加入到一个MinCluster中,如果加入之后MinCluster的直径没有超过T,则直接加入,否则譔CF_new要单独作为一个簇,成为MinCluster的兄弟结点。插入之后注意更新该节点及其所有祖先节点的CF值。 插入新节点后,可能有些节点的孩子数大于了B(或L),此时该节点要分裂。对于Leaf,它现在有L+1个MinCluster,我们要新创建一个Leaf,使它作为原Leaf的兄弟结点,同时注意每新创建一个Leaf都要把它插入到双向链表中。L+1个MinCluster要分到这两个Leaf中,怎么分呢?找出这L+1个MinCluster中距离最远的两个Cluster(根据D2),剩下的Cluster看离哪个近就跟谁站在一起。分好后更新两个Leaf的CF值,其祖先节点的CF值没有变化,不需要更新。这可能导致祖先节点的递归分裂,因为Leaf分裂后恰好其父节点的孩子数超过了B。Nonleaf的分裂方法与Leaf的相似,只不过产生新的Nonleaf后不需要把它放入一个双向链表中。如果是树的根节点要分裂,则树的高度加1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白只对大佬的文章感兴趣

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

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

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

打赏作者

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

抵扣说明:

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

余额充值