想象你在深夜的城市广场观察人群:小吃摊前人们挤成一团,广场边缘三三两两坐着乘凉的人,偶尔还有外卖员骑车飞驰而过。想把这些行人分成“群体”,该用什么标准?如果规定“两人距离小于 1 米就是同伴”,这个尺子在摊位前太挤——大家全连成一片;在广场边又太松——身边无人的人全成了“孤独者”。真实数据就和夜市人群一样,密度高低悬殊,一把固定尺子永远量不出所有真相。 HDBSCAN 的做法很聪明:它不急着定距离,而是先看每个人周围第 k 个邻居离他多远,以此衡量他所在位置的“拥挤程度”;再用这个拥挤程度重新定义两个人之间的“联系成本”。接下来,它在不断放大的视野里观察人群如何聚散离合,最终挑出那些“结伴足够久”的稳定群体。整个过程无需你手动指定邻域半径,能同时发现密集与稀疏的簇,并把落单的点标记为噪声——就像一份自动绘制的夜市人群观察报告。
掌握 HDBSCAN,意味着你可以在客户分群、异常检测等场景中摆脱“拍脑袋定半径”的窘境,用一套自适应密度的聚类流程自动发现结构多样的群体,是数据分析师与机器学习工程师进阶无监督学习的必备技能。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
变密度簇识别 HDBSCAN能自动识别不同密度的簇,DBSCAN固定eps无法做到 不同区域密度差异大,HDBSCAN自适应识别 核心距离与互达距离 reach_dist(a,b) = max(core_dist(a), core_dist(b), dist(a,b)) HDBSCAN密度聚类可视化:展示变密度簇识别、核心...
算法动机
站在夜市入口,你想把逛街的人分成几群。小吃摊前大家挤成一团,广场喷泉边稀稀拉拉坐着休息的人,远处还有几个独来独往的快递员。若规定“两个人距离小于 1 米就算同一伙”,这个标准在摊位前太小——本来就很挤,大家全部连成一片;在喷泉边又太大——坐着的人被拆成好几堆。固定的度量尺度,永远照顾不了所有密度的群体。
传统的 DBSCAN 算法正是如此:它需要你手动设定邻域半径 eps 和最小样本数 min_samples。eps 定得小,只能找到密集簇;eps 定得大,稀疏簇会被淹没或混入大量噪声。真实数据往往像夜市人群一样密度不均,预先拍脑袋定一个半径很难同时覆盖所有情况。
HDBSCAN 的关键想法是:把“固定半径”换成“每个点的局部拥挤程度”。先给每个点量出它的核心距离,再据此重新定义任意两点的互达距离,然后在互达距离的视角下构建层次聚类树,最后依据簇的稳定性自动提取群体。整个过程不需要你指定 eps,因此能同时识别密集簇、稀疏簇和噪声。
这就像你不再用一把固定尺子量所有人,而是先观察每个人周围的拥挤情况,再用“穿越人群的代价”重新衡量人和人之间的距离,最后在俯瞰与放大的变化中看清哪些人真正结伴而行。
核心距离与互达距离
在夜市里判断一个人是否“身处人群”,最直接的办法是看他周围第 k 个离他最近的人有多远。如果他前后左右都是人,第 6 个近邻可能只有半步之遥;如果他在空旷的广场边,第 6 个近邻也许在十几米外。这个距离刻画了他所在位置的拥挤程度。
这个“第 k 近邻距离”在 HDBSCAN 中被称为核心距离。有了核心距离,两个点之间的“真正的联系成本”就不只是直线距离,还要考虑它们所在位置的拥挤程度——于是诞生了互达距离的定义。
核心距离:
互达距离:
就像你从喷泉边走向小吃摊:直线距离也许只有 50 米,但路上要穿过人群(核心距离大),这份“穿越成本”被并入你和摊主的互达距离中。稀疏人群更难被误并入密集组团,而密集组团内部的人依然紧紧贴在一起。
- 核心距离定义$x$ 到最近的第 $k$ 个邻点的距离,$k$ 由 min_samples 决定。
- 互达距离取最大两点的互达距离等于两边核心距离与欧氏距离中的最大者,用拥挤程度修正原始距离。
- 稠密区权重变小当 a、b 都在密集区时,核心距离小,互达距离基本回落到真实距离。
- 稀疏区被抬高当某个点在稀疏区,核心距离大,互达距离以核心距离为主导,稀疏点之间的连接被整体放大。
层次聚类树构建
现在你有了一个被“拥挤程度”重估过的夜市地图。从深夜到凌晨,人群逐渐散去:最紧密的小团体(排队买炸串的一伙人)最后才分开,松散的人群早早就散开。若把“散开”的过程倒过来,从单个个体到整片人群,会形成一棵记录聚散离合的树。
在算法层面,HDBSCAN 以互达距离为权重构建图的最小生成树,然后从最小的互达距离开始不断合并最近的簇,得到一棵层次聚类树(树状图)。树的纵轴是互达距离,横轴是样本;越往下合并距离越小,代表的群体越紧密。
这棵树就像一份夜市人群的“家族族谱”:每一层合并代表一个距离尺度上的亲戚关系,兄弟姐妹靠得最近,表亲稍远,最后所有人在“整个夜市”的尺度上成了一家人。下一步,就是从中挑选出真正长期抱团的群体。
- 聚类合并距离合并两个簇时,用两簇间最近的互达距离作为触发合并的代价。
- 互达距离为权重$d_{\mathrm{mreach}}(a,b)$ 是第 2 节定义的互达距离,不是原始欧氏距离,因此合并过程天然偏袒稠密结构。
- 树不断长高从距离 0 开始,随着互达距离阈值增大,独立点逐步连成簇,簇再合并成大簇,最终形成完整树状图。
稳定性簇提取
拿到这棵族谱树,如果你把所有层级的群体都当成独立队伍,会得到太多小团体;只取根节点,又会把整片夜市混为一谈。怎么挑?一个朴素的标准是:看哪个群体在树的相当长一段高度里一直存在——持续时间越久,越说明它不是偶然相遇。
HDBSCAN 为此引入了 λ 值:λ 等于互达距离的倒数,距离越小(越紧密)λ 越大。随着阈值从下往上增大(λ 减小),一个簇从诞生到消亡覆盖了一段 λ 区间;这个区间的总和乘以簇内点数,就是簇的稳定性。
这就像决定哪些夜市群体值得写进报告:小吃摊前那伙人从深夜一直聚到收摊(λ 区间长),稳定性高,值得保留;两个在路口擦肩而过的路人只在很短的尺度上碰在一起,稳定性低,最终被当作噪声抛弃。噪声点并不是没用的,它们同样是被算法判定为“没结伴够久”的落单者。
- λ 与距离成反比λ 是互达距离的倒数,记录簇从诞生到消亡的紧密程度。
- 簇稳定性求和把簇内每个点的 λ 区间长度累加,得到簇的稳定性。
- 决定保留还是分裂从根向叶子遍历,如果子簇稳定性之和超过父簇,就保留子簇而丢弃父簇。
关键参数调优
虽然 HDBSCAN 不需要指定固定半径,但它也不是魔法。它留下两个旋钮:min_cluster_size 决定“至少几个人才算一群”,min_samples 决定“判断拥挤程度时数几个近邻”。前者像“至少 5 个人才叫队伍”,后者像“看你周围几个人的距离来估计你有多孤单”。
min_samples 越大,核心距离越稳定,但边界越保守,更多点被判为噪声;min_cluster_size 越大,小簇被抹平,只剩大体量群体。两者共同决定了算法对密度的感知粒度。
就像你决定这家夜市至少 10 人聚在一起才可能是有组织的旅行团,少于 10 人的零散小队不值得上报;同时你决定看每个人周围 10 个邻居来判断他是否在人群中。旋钮拧到哪,取决于你眼中“有意义群体”的门槛。
- 经验起点min_samples 与 min_cluster_size 取值相当,保证核心距离估计有足够样本支撑。
- 提高 min_samples提高 min_samples 使核心距离变大,互达距离整体抬高,类边界更保守,簇更少但更纯净。
- 提高 min_cluster_size只影响簇提取阶段,滤除规模过小的簇,适合只想关注大群体的场景。
聚类可视化分析
挑出稳定群体后,你还需要验证这些“人群团”是否真的合理。站在高处俯瞰,紫的点是一伙,绿的点是一伙,红色的是落单者——一眼就能看出算法有没有把两个不同摊位的人错分成一窝。
HDBSCAN 提供了丰富的可视化工具:二维散点图展示聚类结果、树状图展示合并过程、颜色深浅表示每个点属于簇的可信度。对每个点,模型还会输出离群分数 outlier_scores_,分数越高越像噪声。
在二维平面上你可以直接把聚类标签映射为颜色画散点图;在高维数据上可先用 UMAP 或 PCA 降维后再着色。层次树的特点能帮你检查 min_cluster_size 是否过滤掉了有意义的簇,而离群分数分布图反映噪声点与真实簇的分离程度。聚类质量评估常结合轮廓系数、噪声占比和被拆散簇的领域合理性来判断。
这就像摄影师从高处拍下夜市全景,又回看每一段“人群聚散”的延时摄影,确认紫队确实一直待在麻辣烫摊前,绿队确实在广场长椅附近活动。可视化不是事后装饰,而是调参时判断算法行为是否合理的手电筒。
实际应用场景
回归现实,夜市的人群就是你的数据,不同的“群体”就是不同业务场景中的真实类别。
客户分群中,活跃客户像夜市广场上热闹的团,沉睡客户像稀疏散客,HDBSCAN 能一次性识别多个不同密度的用户群体;异常检测中,簇就是正常行为模式,噪声点就是欺诈或故障的异常;地理热点中,它自动找出高密度商圈与低密度街区。
以电商客户分群为例:使用 HDBSCAN 对消费频次、客单价、活跃时长等特征聚类,输出簇标签与离群分数,可直接用于差异化运营。若客户离群分数显著偏高,说明其行为模式与所有簇都不一致,往往对应流失预警或薅羊毛等风险信号。相比 KMeans 需要预设簇数、DBSCAN 需要调半径,HDBSCAN 更适合群体形态未知的探索性分析。
在夜市这个比喻里,应用场景就是帮你写一份“夜市人类学报告”:哪些人值得重点关注、哪些人只是路过、哪些地方永远聚不拢人。算法只是替你观察的眼睛,决策仍在你手里。
AI 应用场景
零售客户分群
阶段:无监督学习 / 特征聚类 / 用户画像
解决的问题:传统 RFM 分群用固定阈值把客户切成几段,区间边界拍脑袋,难以发现“高活跃但低客单”这类变密度细分群体;HDBSCAN 自动发现不同密度的客户群,并标记行为模式异常的离群客户。
具体案例:某电商平台用 HDBSCAN 对 50 万用户的行为指标聚类,自动识别出“夜间高频小额下单”和“周末大宗采购”两个稀疏但真实的小众客群,并发现一批离群分数极高的疑似薅羊毛账号,推送给风控团队复核。
金融交易异常检测
阶段:异常检测 / 无监督建模
解决的问题:正常交易的模式随金额、时段动态变化,DBSCAN 固定半径难以捕捉不同量级的常态交易簇;HDBSCAN 以稳定性提取常态簇,把不落入任何簇的点视为潜在异常。
具体案例:支付风控团队对单笔金额、操作速度、设备指纹等特征执行 HDBSCAN,对新增交易计算离群分数,超过阈值的交易进入人工审核队列,显著降低了误报率。
共享出行热点识别
阶段:时空数据分析 / 地理聚类
解决的问题:城市不同区域供需密度差异极大,中心商圈用车密集、郊区分散,需要不预设半径的聚类来自适应提取高密度、中密度、低密度热点。
具体案例:某共享单车平台对早晚高峰的起点坐标做 HDBSCAN,将识别出的热点用于调度车辆;同时把始终无法成群的低密度区域视为“冷区”,减少无效投放。
Python 演示
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobsfrom sklearn.cluster import HDBSCAN, DBSCAN # 1. 构造变密度数据:密集簇 + 稀疏簇 + 均匀噪声rng = np.random.RandomState(42)X_dense, _ = make_blobs(n_samples=300, centers=[[2, 2]], cluster_std=0.25, random_state=rng)X_sparse, _ = make_blobs(n_samples=150, centers=[[6, 6]], cluster_std=1.2, random_state=rng)noise = rng.uniform(low=-1, high=9, size=(80, 2))X = np.vstack([X_dense, X_sparse, noise]) # 2. HDBSCAN 自动聚类,无需设定邻域半径hdb = HDBSCAN(min_cluster_size=15, min_samples=5)labels_h = hdb.fit_predict(X) # 3. DBSCAN 对照:固定 eps 难以兼顾两种密度db = DBSCAN(eps=0.5, min_samples=5)labels_d = db.fit_predict(X) # 4. 输出簇数与噪声数对比def report(name, labels): n_clusters = len(set(labels)) - (1 if -1 in labels else 0) n_noise = int(np.sum(labels == -1)) print(f"{name}: 簇数 = {n_clusters}, 噪声点 = {n_noise}") report("HDBSCAN", labels_h)report("DBSCAN", labels_d) # 5. 可视化对比fig, axes = plt.subplots(1, 2, figsize=(10, 4))for ax, labels, title in zip(axes, [labels_h, labels_d], ["HDBSCAN", "DBSCAN"]): ax.scatter(X[:, 0], X[:, 1], c=labels, cmap="plasma", s=18) ax.set_title(title) ax.set_xticks([]) ax.set_yticks([])plt.show()
X = np.vstack([X_dense, X_sparse, noise])把三个数据集拼接为一个变密度数据集。hdb = HDBSCAN(min_cluster_size=15, min_samples=5)创建 HDBSCAN 实例,min_cluster_size 控制最小群体规模,min_samples 控制核心距离 k。labels_h = hdb.fit_predict(X)一次完成训练与预测,输出每个点的簇标签,-1 为噪声。db = DBSCAN(eps=0.5, min_samples=5)DBSCAN 需要手动设定 eps=0.5,难以同时适应密集簇和稀疏簇。n_clusters = len(set(labels)) - (1 if -1 in labels else 0)统计去重后的簇数,并排除噪声标签 -1。n_noise = int(np.sum(labels == -1))统计被判定为噪声的点数。
常见误区
误区HDBSCAN 既然自动选半径,那我把数据丢进去就行,无参数可调。
正解HDBSCAN 只是免去了 eps,还需要设定 min_cluster_size 和 min_samples。它们决定“最少多少人算群体、用什么视野评价拥挤程度”,相当于把“拍脑袋定半径”变成了“拍脑袋定群体规模”。
为何常见:因为宣传常说“无需 eps”,初学者很容易误以为它是全自动算法。
误区既然 HDBSCAN 是升级版,以后所有聚类都用 HDBSCAN。
正解在数据集密度比较均匀、簇形简单时,DBSCAN 参数好调、速度快、结果直观;HDBSCAN 构建层次树的计算开销更大,小数据上收益不明显。工具没有绝对优劣,只有匹配问题。
为何常见:看到“更先进”就默认全面超越,忽略了计算成本和简单场景的收益。
误区互达距离不就是欧氏距离换了个名字?反正聚类最后都用距离。
正解互达距离是核心距离与欧氏距离的最大值。处于不同密度区域的两个点,即使直线距离很近,互达距离也可能很大。正是这个“密度修正”让算法可以跨密度尺度比较距离,这是 HDBSCAN 能处理变密度簇的核心。
为何常见:聚类算法通常都基于欧氏距离,先入为主的联想让人忽略 max 操作。
误区聚类算法都要先告诉它分成几类,HDBSCAN 应该也要。
正解HDBSCAN 不要求也不支持指定簇数,它通过稳定性自动决定提取多少个簇。这也是无监督学习的意义所在:在数据形态未知的探索阶段,你不应该先入为主地规定类别数。
为何常见:KMeans 教学太普遍,“先定 K”成为思维定势。
误区标签 -1 的点是算法失败的表现,直接过滤掉能让效果更好。
正解噪声点(标签 -1)恰恰是 HDBSCAN 的重要产出。在异常检测场景里它们就是业务要找的信号;在分群场景里,离群用户可以单独跟进。删除噪声等于把高价值信息当垃圾处理。
为何常见:传统聚类要求所有点都有归属,习惯性想“填满”所有点。
面试题
Q1. HDBSCAN 相比 DBSCAN 最核心的改进是?
- A.聚类速度大幅提升
- B.无需手动设定邻域半径← 正确答案
- C.完全不需要任何参数
- D.只能处理规则球状簇
答案:B。HDBSCAN 用核心距离和互达距离自动适应变密度,无需像 DBSCAN 那样调 eps。A 说反了(层次构建更重),C 过于绝对(仍需 min_cluster_size / min_samples),D 与算法特性相反。
Q2. 互达距离的定义是取三个值中的?
- A.最小者
- B.最大者← 正确答案
- C.平均者
- D.中位者
答案:B。互达距离取 max{核心距离(a), 核心距离(b), 欧氏距离(a,b)}。取最小会丢失密度修正信息,取平均或中位则会引入没有理论依据的平滑操作。
Q3. 核心距离 core_k(x) 指的是?
- A.到最近邻的距离
- B.到第 k 近邻的距离← 正确答案
- C.到簇中心的距离
- D.到最远邻居的距离
答案:B。核心距离 = 点到第 k 个近邻的距离,反映局部拥挤程度。A 是 k=1 的特例;C 是质心距离;D 与定义相反。
Q4. HDBSCAN 中 cluster_selection_epsilon 的作用是?
- A.直接指定聚类的簇数
- B.过滤互达距离过大的簇← 正确答案
- C.控制特征降维的维度
- D.提高计算收敛速度
答案:B。该参数设置互达距离上限,只有在该尺度内稳定存在的簇才会被提取,避免大量依靠过大距离连成的小簇。簇数由稳定性自动决定,与特征维度和速度无关。
Q5. 簇稳定性 s(C) 衡量的是?
- A.簇内点的数量总和
- B.簇内点 λ 区间长度之和← 正确答案
- C.簇质心到边界的半径
- D.簇内两两点的平均距离
答案:B。s(C) = Σ(λ_max − λ_min),λ 区间越长说明点在该簇中维持越久。A 只是规模,C 是半径,D 是平均距离,都不含“寿命”信息。
Q6. 下列哪些场景适合用 HDBSCAN?
- A.数据包含多个密度差异很大的簇← 正确答案
- B.数据中混有大量无标签噪声点← 正确答案
- C.业务要求必须恰好分成 3 类
- D.需要非常快速但简单的聚类
答案:AB。HDBSCAN 擅长变密度 + 噪声场景。C 需要固定 K,应选 KMeans 或谱聚类;D 中 HDBSCAN 计算更重,DBSCAN、KMeans 更快。
Q7. 层次树剪枝时,若子簇稳定性之和大于父簇稳定性,应当?
- A.保留父簇作为最终簇
- B.分裂成子簇作为最终簇← 正确答案
- C.合并两个子簇并丢弃
- D.把父簇标记为噪声
答案:B。子簇稳定性之和更大,说明父簇把两个明显独立的群体硬包在一起,拆开更合理。保留父簇则导致欠分割,合并子簇无逻辑,父簇更不应被标记为噪声。
Q8. HDBSCAN 结果中标签 -1 的点的含义,下列说法正确的有?
- A.该点被判定为噪声点← 正确答案
- B.该点被归入密度最高簇
- C.该点可能是业务异常← 正确答案
- D.该点代表数据缺失
答案:AC。标签 -1 表示该点不属于任何稳定簇,即噪声点;在业务上往往是异常信号。B 与定义相反,D 中数据缺失应由预处理流程处理,与聚类标签无关。
Q9. 关于 min_samples 与 min_cluster_size 下列说法正确的有?
- A.min_samples 影响核心距离的计算← 正确答案
- B.min_cluster_size 控制提取簇的最小规模← 正确答案
- C.min_samples 过大可能导致更多点被标记为噪声← 正确答案
- D.min_samples 越大聚类速度一定越快
答案:ABC。min_samples 是第 k 近邻中的 k,直接影响核心距离与互达距离;min_cluster_size 是提取阶段的剪枝门槛;min_samples 过大会抬高互达距离,边界保守、噪声增多。D 没有依据,计算量不因该参数下降。
Q10. HDBSCAN 构建层次聚类树所依赖的核心图结构是?
- A.平衡二叉树结构
- B.最小生成树结构← 正确答案
- C.双向链表结构
- D.哈希表结构
答案:B。算法先构建以互达距离为边权的最小生成树,再按边权从小到大合并出树状图。平衡二叉树是后续检索的数据结构,双向链表和哈希表与层次树构建无关。