聚类分析算法——DBSCAN(密度聚类)算法详解

聚类分析算法——DBSCAN(密度聚类)算法详解

        本文要全面、深入地介绍理解 DBSCAN(Density-Based Spatial Clustering of Applications with Noise),我们需要从 算法的核心思想、步骤、底层原理、参数选择,以及 代码实现细节 上进行详细剖析。


1. DBSCAN 算法核心思想

        DBSCAN 是一种基于密度的聚类算法,旨在发现任意形状的簇,并且对 噪声点(outliers)具有鲁棒性(健壮性)。它通过在数据空间中找到高密度区域,将这些区域作为簇,同时把孤立点(密度低的点)归为噪声。

DBSCAN 的基本思想是:

  • 在某个点的 邻域半径(ε,epsilon) 内,如果有足够多的点(超过一个阈值 minPts),就认为这个区域是一个 高密度区域,可以扩展成一个簇。
  • 一个簇通过密度相连(density-connected) 的点进行扩展。
  • 无法归属于任何簇的点被认为是噪声点
数据可视化

        可以试试DBSCAN可视化网址来直接了解执行的流程

执行过程:

示例:

① 数据处理前:

参数解释:epsilon指的为半径,minPoints指的是在半径为1的空间里有四个小球即可扩散

② 数据处理后:


2. DBSCAN 的基本概念

  1. ε-邻域(Epsilon-neighborhood):
    对于某个点 p,以半径 ε 为边界的区域内所有的点称为该点的 ε-邻域。
  2. 核心点(Core Point)
    如果一个点 p 的 ε-邻域内至少有 minPts 个点(包括 p 自己),那么它被称为核心点。
  3. 边界点(Border Point)
    如果一个点 p 在某个核心点的 ε-邻域内,但自身不是核心点,它被称为边界点。
  4. 噪声点(Noise Point)
    如果一个点既不是核心点,也不属于任何核心点的邻域,它被认为是噪声点。
  5. 密度直达(Directly Density-Reachable)
    如果点 p 是核心点,并且点 q 在 p 的 ε-邻域内,那么 q 被称为从 p 密度直达
  6. 密度可达(Density-Reachable)
    如果存在一条核心点链表(p1→p2→...→pn​),使得每个点从前一个点密度直达,且 p1=p,pn=q,则 q 是从 p 密度可达 的。
  7. 密度相连(Density-Connected)
    如果存在一个点 o,使得 p 和 q 都从 o 密度可达,则称 p 和 q 是密度相连的。

3. DBSCAN 算法步骤

  1. 初始化
    从数据集中任意选择一个点 p,判断它是否为核心点(即 ε 邻域内是否包含至少 minPts 个点)。
  2. 扩展簇
    如果 p 是核心点,则开始一个新簇,将 p 及其邻域中的点加入簇中,并不断对新的核心点的邻域进行扩展。
  3. 处理噪声点
    如果一个点既不在任何簇中,也不满足成为核心点的条件,则将其标记为噪声点。
  4. 重复处理
    继续检查所有未访问的点,直到所有点都被访问为止。

4. DBSCAN 伪代码

DBSCAN(D, ε, minPts): C = 0 # 初始化簇标签 for each unvisited point P in dataset D: mark P as visited Neighbors = getNeighbors(P, ε) # 获取邻域内的所有点 if size(Neighbors) < minPts: mark P as NOISE # 认为该点是噪声 else: C = C + 1 # 创建新簇 expandCluster(P, Neighbors, C, ε, minPts) expandCluster(P, Neighbors, C, ε, minPts): add P to cluster C for each point Q in Neighbors: if Q is not visited: mark Q as visited NeighborsQ = getNeighbors(Q, ε) if size(NeighborsQ) >= minPts: Neighbors = Neighbors ∪ NeighborsQ if Q is not yet assigned to any cluster: add Q to cluster C 

5. DBSCAN 的时间复杂度分析

  • 邻域查询:在每次扩展时,需要查找一个点的 ε 邻域。如果使用 KD-Tree 或 Ball-Tree 等空间索引结构,这个操作的复杂度为 O(log⁡n)。

总体复杂度:如果对每个点进行邻域查询,算法的时间复杂度为 O(n⋅log⁡n)。如果不使用索引结构,最坏情况下是

O(n^{2})


6. DBSCAN 的 Python 实现

我们使用 scikit-learn 中的 DBSCAN 实现,并演示如何手动实现核心逻辑。

6.1 使用 scikit-learn 的 DBSCAN

from sklearn.cluster import DBSCAN import numpy as np # 生成示例数据 X = np.array([[1, 2], [2, 2], [2, 3], [8, 7], [8, 8], [25, 80]]) # 初始化 DBSCAN 模型 db = DBSCAN(eps=3, min_samples=2).fit(X) # 获取聚类标签 labels = db.labels_ print("Cluster labels:", labels) 

输出:

Cluster labels: [ 0 0 0 1 1 -1]

解释:

  • 标签为 -1 的点表示噪声点。
  • 其他标签表示该点属于的簇。

6.2 手动实现 DBSCAN 的核心逻辑

import numpy as np def dbscan(X, eps, minPts): labels = [-1] * len(X) # 初始化所有点为未分类(-1 表示噪声) C = 0 # 当前簇标签 def region_query(P): return [i for i, Q in enumerate(X) if np.linalg.norm(P - Q) <= eps] def expand_cluster(P, neighbors): labels[P] = C i = 0 while i < len(neighbors): Q = neighbors[i] if labels[Q] == -1: # 如果 Q 是噪声点,重新标记为簇点 labels[Q] = C elif labels[Q] == -1: # 如果 Q 还未分类 labels[Q] = C Q_neighbors = region_query(X[Q]) if len(Q_neighbors) >= minPts: neighbors += Q_neighbors # 扩展邻域 i += 1 for P in range(len(X)): if labels[P] == -1: neighbors = region_query(X[P]) if len(neighbors) < minPts: labels[P] = -1 # 标记为噪声 else: C += 1 # 创建新簇 expand_cluster(P, neighbors) return labels # 示例数据 X = np.array([[1, 2], [2, 2], [2, 3], [8, 7], [8, 8], [25, 80]]) # 运行 DBSCAN labels = dbscan(X, eps=3, minPts=2) print("Cluster labels:", labels) 


7. 参数选择与调优

  1. ε(eps)
    • ε 决定了邻域的大小。如果太小,簇会分散;太大,簇会合并。
  2. minPts
    • 一般来说,minPts ≥ 数据维度的两倍。例如对于二维数据,可以设置 minPts = 4
  3. 调参思路
ε(eps)小,minPts大:一般是半径ε小一点,minPts 大一点

可以通过 k距离图(k-distance graph)来选择合适的 ε。


8. DBSCAN 的优缺点

优点:

  • 可以发现任意形状的簇。
  • 不需要预先指定簇的数量。
  • 对噪声有鲁棒性。

缺点:

  • 当簇的密度差异较大时,效果不佳。
  • 高维数据中的性能较差,非常消耗CPU和GPU以及内存性能。
  • 需要合理选择 ε 和 minPts 参数。

9. 总结

        DBSCAN 是一种基于密度的聚类算法,特别适用于发现任意形状的簇,并且具有处理噪声点的能力。通过合理选择参数 ε 和 minPts,它可以在空间数据分析、图像处理、异常检测等领域发挥重要作用。

Read more

清华团队首发OpenClaw研究报告:AI智能体生态闭环全解析

清华团队首发OpenClaw研究报告:AI智能体生态闭环全解析

🍃 予枫:个人主页 📚 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》《Java 面试刷题指南》 💻 Debug 这个世界,Return 更好的自己! 引言 近期“龙虾”OpenClaw持续爆火,GitHub星标数一路飙升,成为AI智能体领域的现象级开源项目。就在这时,清华沈阳教授团队重磅首发两份OpenClaw专项研究报告,从理论到实践、从自我研究到生态布局,给出了最全面的解读,堪称OpenClaw学习的“官方指南”,程序员和AI从业者必看! 文章目录 * 引言 * 一、OPENCLAW双报告核心概况 * 1.1 《OpenClaw发展研究报告1.0》:严谨迭代的生态指南 * 1.2 《OpenClaw自我研究报告1.0》:AI研究AI的标杆实验 * 二、OPENCLAW领域阶段性进展 * 2.1 理论研究:筑牢生态基础,扩大科普影响力 * 2.2 模型研发:

手把手教你用LLaMA-Factory微调Qwen2.5-VL-7B-Instruct进行印章识别(含完整配置流程)

从零到一:基于LLaMA-Factory与Qwen2.5-VL-7B-Instruct构建高精度印章识别系统 最近在做一个文档智能处理的项目,其中有个需求是从各类扫描件和照片里自动提取印章上的文字信息。试过一些OCR通用方案,效果总是不尽如人意——要么把印章的红色圆形边框也识别进去,要么对模糊、倾斜、背景复杂的印章束手无策。后来我们把目光投向了多模态大模型,特别是那些能“看懂”图片的视觉语言模型。经过一番折腾,最终用LLaMA-Factory微调Qwen2.5-VL-7B-Instruct模型,成功搭建了一套针对印章识别场景的专用方案。整个过程踩了不少坑,也积累了一些实战经验,今天就来详细聊聊怎么一步步实现它。 这篇文章不是简单的操作手册,我会结合自己的实践,深入聊聊为什么选择这个技术栈、数据该怎么准备才有效、训练过程中有哪些关键参数会直接影响效果,以及如何把训练好的模型真正用起来。无论你是刚开始接触多模态模型微调,还是已经在寻找更优的垂直领域解决方案,相信这些细节都能给你带来启发。 1. 技术选型与项目环境搭建 为什么是Qwen2.5-VL-7B-Instruct?在开始动

llama.cpp 部署 Qwen3-14B-Claude-4.5-Opus-High-Reasoning-Distill-GGUF

模型:Qwen3-14B-Claude-4.5-Opus-High-Reasoning-Distill-GGUF "model": "Qwen3-14B" 显存:21~25GB max-model-len :40960 并发: 4 部署服务器:DGX-Spark-GB10 120GB 生成速率:13 tokens/s (慢的原因分析可见https://blog.ZEEKLOG.net/weixin_69334636/article/details/158497823?spm=1001.2014.3001.5501) 部署GGUF格式的模型有3种方法 对比项Ollamallama.cppLM Studio/OpenWebUI上手难度⭐ 最简单⭐⭐⭐ 需编译⭐ 图形界面推理性能🔶 中等🥇 最强🔶 中等GPU控制有限完全可控有限API服务开箱即用需手动启动内置适合场景快速部署/生产性能调优/研究本地体验

体验Stable Diffusion 3.5省钱攻略:比买显卡省90%,按需付费

体验Stable Diffusion 3.5省钱攻略:比买显卡省90%,按需付费 你是不是也遇到过这样的情况:作为自由职业者,客户突然发来一个AI绘画项目需求,说“先做个样图看看效果”。你心里一紧——要测试 Stable Diffusion 3.5 吗?可自己电脑跑不动,租专业显卡又太贵,动辄每月上千元,就为了做几次测试,实在不划算。 别急,我最近发现了一个超低成本的解决方案:用云端算力平台按小时计费的方式,部署 Stable Diffusion 3.5 镜像,完成一次高质量图像生成测试,总成本不到10块钱!相比动辄上万元买显卡或每月固定租赁高端GPU,直接省下90%以上的费用。 这篇文章就是为你量身打造的“小白友好型”实操指南。我会带你一步步从零开始,在ZEEKLOG星图提供的预置镜像环境中,快速启动 Stable Diffusion 3.5,生成专业级图像,并掌握关键参数调优技巧。无论你是设计师、