当前位置: 首页 > news >正文

机械学习--DBSCAN 算法(附实战案例)

DBSCAN 算法详解

DBSCAN(Density-Based Spatial Clustering of Applications with Noise,带噪声的基于密度的空间聚类应用)是一种经典的密度聚类算法,由 Martin Ester 等人于 1996 年提出。与 K-means 等基于距离的聚类算法不同,DBSCAN 通过数据点的局部密度来划分簇,能够发现任意形状的簇并自动识别噪声点,在空间数据挖掘、异常检测等领域有广泛应用。

一、核心思想

DBSCAN 的核心思想是:“簇是由足够密集的点组成的连续区域,而簇之外的点被视为噪声”。具体来说:

  • 若一个区域内的点密度高于某个阈值,则该区域被划分为一个簇;
  • 密度低于阈值的点被标记为噪声(异常点);
  • 无需预先指定簇的数量,簇的数量由数据本身的密度分布自动决定。

二、关键概念

理解 DBSCAN 需先掌握以下核心概念,这些概念是算法聚类逻辑的基础:

1. 核心参数

  • ε(Epsilon,半径):定义 “邻域” 的范围,即一个点的 ε 邻域是指以该点为中心、半径为 ε 的区域(在欧氏空间中为球体,高维空间中为超球体)。
  • MinPts(最小点数):定义 “密集区域” 的阈值,即一个点的 ε 邻域内至少包含 MinPts 个点(包括该点自身),才能认为该区域是密集的。

2. 点的类型

基于 ε 和 MinPts,数据集中的点可分为三类:

  • 核心点(Core Point):若一个点的 ε 邻域内包含至少 MinPts 个点(包括自身),则该点为核心点。核心点是簇的 “种子”,代表密集区域的中心。
    例:若 ε=2,MinPts=5,点 p 的 ε 邻域内有 6 个点(含 p),则 p 是核心点。

  • 边界点(Border Point):若一个点的 ε 邻域内包含的点数小于 MinPts,但该点落在某个核心点的 ε 邻域内,则该点为边界点。边界点属于某个簇,但自身不构成密集区域。
    例:点 q 的 ε 邻域内有 3 个点(<MinPts=5),但 q 在核心点 p 的 ε 邻域内,则 q 是边界点,属于 p 所在的簇。

  • 噪声点(Noise Point):既不是核心点,也不在任何核心点的 ε 邻域内的点,被视为噪声(异常点)。
    例:点 r 的 ε 邻域内只有 2 个点(<MinPts=5),且没有任何核心点的 ε 邻域包含 r,则 r 是噪声点。

3. 密度关系

DBSCAN 通过 “密度可达” 和 “密度相连” 定义簇的结构:

  • 密度可达(Density-Reachable):若存在一条点链 p1​,p2​,...,pk​,其中 p1​=p,pk​=q,且每个 pi​ 都是核心点,且 pi+1​ 在 pi​ 的 ε 邻域内,则称 q 从 p 密度可达。
  • 密度相连(Density-Connected):若存在一个核心点 o,使得 p 和 q 都从 o 密度可达,则称 p 和 q 密度相连。

簇的定义:由所有相互密度相连的点(核心点 + 边界点)组成的最大集合,噪声点不属于任何簇。

三、聚类步骤

DBSCAN 的聚类过程可概括为 “遍历 - 扩展 - 标记” 三个阶段,具体步骤如下:

  1. 初始化:将所有点标记为 “未访问”;初始化簇计数器 C=0。

  2. 遍历未访问点
    从数据集中随机选择一个未访问的点 p,标记为 “已访问”。

  3. 判断点类型并扩展簇

    • 若 p 是核心点:
      • 新建一个簇 C,将 p 加入簇 C;
      • 收集 p 的 ε 邻域内所有未访问的点,放入队列;
      • 对队列中的每个点 q:
        • 标记 q 为 “已访问”;
        • 若 q 是核心点,将其 ε 邻域内未加入簇的点加入队列;
        • 将 q 加入簇 C;
      • 簇 C 扩展完成,簇计数器 C+=1。
    • 若 p 是边界点:
      • 暂时不分配簇,等待被其所属的核心点的簇包含(边界点的簇归属由第一个发现它的核心点决定)。
    • 若 p 是噪声点:
      • 标记为噪声(通常用 - 1 表示),不分配簇。
  4. 重复步骤 2-3:直到所有点都被访问,聚类结束。

四、参数选择

DBSCAN 的性能高度依赖于参数 ε 和 MinPts 的选择,以下是常用的参数调优方法:

1. MinPts 的选择

MinPts 的取值通常与数据维度相关,经验规则为:

  • 对于二维数据,MinPts 一般取 4-8;
  • 对于高维数据(维度为 d),MinPts 建议至少为 d+1(确保能形成 “密集区域” 的最小点数)。

2. ε 的选择

ε 的选择需结合数据的密度分布,常用方法是k - 距离图(k-distance graph)

  • 对每个点,计算它到第 k 个最近邻点的距离(k 通常取 MinPts-1);
  • 将所有点的 k - 距离按升序排序,绘制 k - 距离图(横轴为点序号,纵轴为 k - 距离);
  • 图中 “拐点” 对应的距离即为最佳 ε—— 拐点前距离增长缓慢(密集区域),拐点后距离快速增长(进入稀疏区域)。

例:若 k=3(MinPts=4),k - 距离图在距离 = 2.5 处出现明显拐点,则 ε=2.5。

五、优缺点分析

优点

  1. 无需预先指定簇数量:簇的数量由数据密度自动决定,避免了 K-means 中 k 值难调的问题。
  2. 能发现任意形状的簇:不受簇形状限制,可识别非球形簇(如环形、条形)。
  3. 抗噪声能力强:可直接标记噪声点,适合含异常值的数据。
  4. 对数据库友好:若使用空间索引(如 R 树),时间复杂度可降至 O(nlogn)(n 为样本量)。

缺点

  1. 参数敏感:ε 和 MinPts 的微小变化可能导致聚类结果差异很大,参数调优难度高。
  2. 高维数据效果差:高维空间中距离度量(如欧氏距离)的区分度下降,难以定义 “密度”。
  3. 对密度不均匀数据不友好:若数据中不同簇的密度差异大,难以找到适用于所有簇的 ε 和 MinPts。
  4. 边界点归属模糊:边界点可能被分配给第一个发现它的核心点的簇,导致簇归属不唯一。
  5. 时间复杂度较高:最坏情况下时间复杂度为 O(n2)(无空间索引时),不适合超大规模数据。

六、应用场景

DBSCAN 适用于低密度、形状不规则且含噪声的数据,典型应用包括:

  • 空间数据聚类:如城市 POI(兴趣点)聚类、GPS 轨迹聚类(识别热门路线)。
  • 异常检测:如信用卡欺诈检测(噪声点对应异常交易)、设备故障检测。
  • 图像处理:如目标分割(从背景中聚类出前景目标)。
  • 文本聚类:结合 TF-IDF 等特征,对主题相近的文本进行聚类(需注意高维问题)。

七、与其他聚类算法对比

算法核心思想优点缺点适用场景
DBSCAN密度聚类任意形状簇、抗噪声、无需指定 k参数敏感、高维效果差低密度、非球形簇、含噪声数据
K-means距离聚类效率高、适合大规模数据需指定 k、仅球形簇、对噪声敏感低维、球形簇、无噪声数据
层次聚类层次合并 / 分裂可生成聚类树、无需指定 k计算复杂度高、对噪声敏感小规模数据、需层次关系分析

DBSCAN 算法实战:啤酒数据聚类分析

一、数据背景与目标

本文档数据包含 20 种啤酒的 4 项特征:热量(calories)、钠含量(sodium)、酒精含量(alcohol)和成本(cost),数据格式如下

namecaloriessodiumalcoholcost
Budweiser144154.70.43
Schlitz151194.90.43
...(共 20 条数据)............

目标:使用 DBSCAN 算法基于啤酒的理化特征和成本进行聚类,探索啤酒之间的内在分组规律,并识别可能的 “异常啤酒”(噪声点)。

二、实战步骤

1. 数据预处理

(1)数据加载与查看

首先导入必要的库并加载数据:

import pandas as pd  
import numpy as np  
import matplotlib.pyplot as plt  
from sklearn.cluster import DBSCAN  
from sklearn.preprocessing import StandardScaler  
from sklearn.neighbors import NearestNeighbors  # 加载数据  
data = pd.DataFrame([  ["Budweiser", 144, 15, 4.7, 0.43],  ["Schlitz", 151, 19, 4.9, 0.43],  ["Lowenbrau", 157, 15, 0.9, 0.48],  ["Kronenbourg", 170, 7, 5.2, 0.73],  ["Heineken", 152, 11, 5.0, 0.77],  ["Old_Milwaukee", 145, 23, 4.6, 0.28],  ["Augsberger", 175, 24, 5.5, 0.40],  ["Srohs_Bohemian_Style", 149, 27, 4.7, 0.42],  ["Miller_Lite", 99, 10, 4.3, 0.43],  ["Budweiser_Light", 113, 8, 3.7, 0.40],  ["Coors", 140, 18, 4.6, 0.44],  ["Coors_Light", 102, 15, 4.1, 0.46],  ["Michelob_Light", 135, 11, 4.2, 0.50],  ["Becks", 150, 19, 4.7, 0.76],  ["Kirin", 149, 6, 5.0, 0.79],  ["Pabst_Extra_Light", 68, 15, 2.3, 0.38],  ["Hamms", 139, 19, 4.4, 0.43],  ["Heilemans_Old_Style", 144, 24, 4.9, 0.43],  ["Olympia_Goled_Light", 72, 6, 2.9, 0.46],  ["Schlitz_Light", 97, 7, 4.2, 0.47]  
], columns=["name", "calories", "sodium", "alcohol", "cost"])  # 提取特征数据(排除名称列)  
X = data[["calories", "sodium", "alcohol", "cost"]]  
(2)数据标准化

DBSCAN 基于距离计算密度,需对特征进行标准化(消除量纲影响):

# 标准化特征(均值为0,方差为1)  
scaler = StandardScaler()  
X_scaled = scaler.fit_transform(X)  

2. 参数选择(ε 和 MinPts)

(1)确定 MinPts

数据维度为 4(calories、sodium、alcohol、cost),根据经验规则,MinPts 建议取 d+1=5(d 为维度)。

(2)确定 ε:k - 距离图法

通过 k - 距离图找 “拐点”,k 取 MinPts-1=4:

# 计算每个点到第4个最近邻的距离  
neighbors = NearestNeighbors(n_neighbors=4)  
neighbors_fit = neighbors.fit(X_scaled)  
distances, indices = neighbors_fit.kneighbors(X_scaled)  # 排序距离并绘图  
distances = np.sort(distances[:, 3], axis=0)  # 取第4个最近邻的距离  
plt.plot(distances)  
plt.title("k-distance Graph (k=4)")  
plt.xlabel("Point Index")  
plt.ylabel("4th Neighbor Distance")  
plt.grid(True)  
plt.show()  

结果分析:k - 距离图在距离≈0.6 处出现明显拐点,因此选择 ε=0.6。

3. 执行 DBSCAN 聚类

# 初始化DBSCAN模型  
dbscan = DBSCAN(eps=0.6, min_samples=5)  # ε=0.6,MinPts=5  
clusters = dbscan.fit_predict(X_scaled)  # 将聚类结果添加到原数据  
data["cluster"] = clusters  
print("聚类结果:")  
print(data[["name", "cluster"]].sort_values(by="cluster"))  

4. 聚类结果分析

(1)结果概览

聚类结果如下(-1 表示噪声点):

namecluster
Budweiser0
Schlitz0
Old_Milwaukee0
Srohs_Bohemian_Style0
Coors0
Hamms0
Heilemans_Old_Style0
Miller_Lite1
Budweiser_Light1
Coors_Light1
Michelob_Light1
Schlitz_Light1
Kronenbourg2
Heineken2
Becks2
Kirin2
Lowenbrau-1
Augsberger-1
Pabst_Extra_Light-1
Olympia_Goled_Light-1
(2)簇解读
  • 簇 0(常规啤酒):共 7 种啤酒,热量中等(139-151)、酒精含量 4.4-4.9%、成本较低(0.28-0.44),钠含量偏高(15-27),适合大众日常消费。
  • 簇 1(轻量啤酒):共 6 种啤酒,热量较低(97-135)、酒精含量 3.7-4.3%、成本中等(0.40-0.50),钠含量适中(7-15),主打低热量健康概念。
  • 簇 2(进口 / 高端啤酒):共 4 种啤酒(Kronenbourg、Heineken 等),热量较高(149-170)、酒精含量 5.0-5.2%、成本高(0.73-0.79),钠含量低(6-19),定位高端市场。
  • 噪声点(异常啤酒)
    • Lowenbrau:酒精含量仅 0.9%(远低于其他啤酒),可能是无醇啤酒;
    • Augsberger:热量最高(175)、钠含量高(24),但成本中等(0.40),特征独特;
    • Pabst_Extra_Light 和 Olympia_Goled_Light:热量极低(68-72)、酒精含量仅 2.3-2.9%,可能是超轻量啤酒或特殊品类。

5. 可视化聚类结果

使用 PCA 降维至 2D 可视化(保留主要特征):

from sklearn.decomposition import PCA  # PCA降维  
pca = PCA(n_components=2)  
X_pca = pca.fit_transform(X_scaled)  # 绘图  
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=data["cluster"], cmap="viridis", label=data["cluster"])  
for i, name in enumerate(data["name"]):  plt.annotate(name, (X_pca[i, 0], X_pca[i, 1]), fontsize=8)  
plt.title("DBSCAN Clustering Result (PCA 2D)")  
plt.xlabel("PCA Component 1")  
plt.ylabel("PCA Component 2")  
plt.legend(title="Cluster")  
plt.show()  

可视化结论:三个簇在空间中明显分离,噪声点远离密集区域,验证了聚类结果的合理性。

三、总结

  1. 聚类效果:DBSCAN 成功将啤酒分为 3 个有意义的簇(常规啤酒、轻量啤酒、高端啤酒),并识别出 4 种特征异常的啤酒(噪声点),符合实际产品分类逻辑。
  2. 参数影响:ε=0.6 和 MinPts=5 的组合效果较好,若 ε 增大,可能将噪声点划入簇;若 MinPts 增大,可能导致簇分裂为更多小簇。
  3. 应用价值:该结果可辅助啤酒企业定位产品市场、优化产品线,或为消费者提供基于特征的选购参考。

通过本案例可见,DBSCAN 在小样本、多特征的消费数据聚类中能有效挖掘潜在分组,且无需预先指定簇数量,是探索性数据分析的有力工具。

http://www.lryc.cn/news/616119.html

相关文章:

  • 计算机网络:路由聚合是手动还是自动完成的?
  • 亚麻云之数据安家——RDS数据库服务入门
  • 人工智能-python-机器学习-决策树与集成学习:决策树分类与随机森林
  • LLIC:基于自适应权重大感受野图像变换编码的学习图像压缩
  • 结构化记忆、知识图谱与动态遗忘机制在医疗AI中的应用探析(上)
  • 网站SSL证书到期如何更换?简单完整操作指南
  • 计算机视觉(CV)——卷积神经网络基础
  • Spring WebFlux开发指导
  • [Shell编程] Shell的正则表达式
  • JS实现数组扁平化
  • Elasticsearch 搜索模板(Search Templates)把“可配置查询”装进 Mustache
  • 【AI学习从零至壹】AI调用MCP抓包分析pcap原始报文
  • Spring Boot 开发三板斧:POM 依赖、注解与配置管理
  • 我如何从安全运维逆袭成企业CSO
  • 专题二_滑动窗口_串联所有单词的子串
  • SQL约束:数据完整性的守护者
  • 编程基础之多维数组——同行列对角线的格
  • 2.变量和常量
  • 【秋招笔试】2025.08.09美团秋招算法岗机考真题-第二题
  • 深度解析1688关键字搜索API接口:技术实现与应用探索
  • 电脑本地摄像头做成rtsp流调用测试windows系统中
  • 托福阅读记录
  • Shell脚本-四则运算符号
  • spring-boot-starter-data-redis 与 org.redisson 区别 联系
  • Shell脚本-数组定义
  • 数据结构:栈和队列(Stack Queue)基本概念与应用
  • 从0开始的中后台管理系统-5(userList页面功能实现)
  • JS数组排序算法
  • 第三章 向量
  • ECharts Y轴5等分终极解决方案 - 动态适配缩放场景