深入解析HDBSCAN聚类算法的工作原理
hdbscan 项目地址: https://gitcode.com/gh_mirrors/hd/hdbscan
HDBSCAN(Hierarchical Density-Based Spatial Clustering of Applications with Noise)是一种先进的密度聚类算法,它通过构建层次化的聚类结构并基于聚类稳定性提取最终结果,能够有效处理不同密度的聚类并识别噪声点。本文将深入解析HDBSCAN算法的工作原理,帮助读者全面理解这一强大的聚类工具。
算法概述
HDBSCAN是对传统DBSCAN算法的扩展和改进,主要解决了以下问题:
- 自动确定最优聚类数量,无需预先指定簇数
- 能够处理不同密度的聚类
- 对噪声点有更好的鲁棒性
- 提供层次化的聚类结果
算法工作流程可分为五个关键步骤,我们将结合示例数据逐步解析每个步骤。
示例数据准备
为了更好地理解算法,我们首先生成一个包含100个点的测试数据集,这个数据集包含两个半月形簇和两个高斯分布簇:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
moons, _ = datasets.make_moons(n_samples=50, noise=0.05)
blobs, _ = datasets.make_blobs(n_samples=50, centers=[(-0.75,2.25), (1.0, 2.0)], cluster_std=0.25)
test_data = np.vstack([moons, blobs])
plt.scatter(test_data[:,0], test_data[:,1], alpha=0.5)
plt.show()
第一步:空间转换与核心距离
HDBSCAN首先通过空间转换使算法对噪声更加鲁棒。核心思想是"降低海平面",让稀疏的噪声点相互远离,同时保持密集区域的点距离不变。
具体实现步骤:
-
对每个点计算其到第k个最近邻的距离,称为核心距离(core distance)
-
定义新的距离度量——相互可达距离(mutual reachability distance):
d_mreach-k(a,b) = max{core_k(a), core_k(b), d(a,b)}
这种转换的效果是:
- 密集点(核心距离小)保持原始距离
- 稀疏点(核心距离大)被推远,至少相距它们的核心距离
# 伪代码示例
def mutual_reachability_distance(a, b, core_dist_a, core_dist_b, original_distance):
return max(core_dist_a, core_dist_b, original_distance)
第二步:构建最小生成树
在相互可达距离的基础上,HDBSCAN构建一个最小生成树(MST)。这个树结构包含了数据点之间的重要连接关系,是后续步骤的基础。
最小生成树的构建可以使用Prim算法或更高效的Dual Tree Boruvka算法(适用于度量空间)。构建完成后,我们可以可视化这个最小生成树:
clusterer = hdbscan.HDBSCAN(min_cluster_size=5, gen_min_span_tree=True)
clusterer.fit(test_data)
clusterer.minimum_spanning_tree_.plot(edge_cmap='viridis', edge_alpha=0.6)
第三步:构建聚类层次结构
基于最小生成树,HDBSCAN通过以下步骤构建层次聚类:
- 按距离升序排序所有边
- 逐步添加边,使用并查集(Union-Find)数据结构跟踪连通分量
- 记录每个连通分量形成和分裂的过程
这个过程产生了一个完整的层次聚类结构,可以表示为树状图(dendrogram):
clusterer.single_linkage_tree_.plot(cmap='viridis')
第四步:压缩聚类树
原始层次结构通常过于复杂,HDBSCAN通过以下规则压缩树结构:
- 设定最小簇大小参数(min_cluster_size)
- 遍历层次结构,当分裂产生的小于最小簇大小的子簇时:
- 视为"点从簇中脱落"
- 保留父簇身份,记录脱落点和距离
- 对于产生两个足够大子簇的分裂,保留为真正的簇分裂
压缩后的树结构更加简洁,同时保留了关键聚类信息:
clusterer.condensed_tree_.plot()
第五步:提取稳定簇
最后一步是从压缩树中提取稳定的簇,HDBSCAN使用以下算法:
-
定义λ=1/distance作为持久性度量
-
对每个簇计算稳定性:
- λ_birth: 簇形成时的λ值
- λ_death: 簇分裂时的λ值
- 对簇中每个点p,计算λ_p(点脱落时的λ值)
- 稳定性 = Σ(λ_p - λ_birth)
-
自底向上遍历树:
- 初始选择所有叶簇
- 比较父簇稳定性与其子簇稳定性之和
- 选择稳定性较大的一方,取消选择另一方
clusterer.condensed_tree_.plot(select_clusters=True)
最终聚类结果
经过上述步骤,HDBSCAN生成最终聚类结果,包括:
- 簇标签(噪声点标记为-1)
- 每个点的簇成员概率(归一化的λ值)
我们可以可视化最终结果,用颜色表示簇归属,用饱和度表示成员强度:
palette = sns.color_palette()
cluster_colors = [sns.desaturate(palette[col], sat) if col >= 0 else (0.5,0.5,0.5)
for col, sat in zip(clusterer.labels_, clusterer.probabilities_)]
plt.scatter(test_data[:,0], test_data[:,1], c=cluster_colors)
plt.show()
算法优势与应用
HDBSCAN相比传统聚类算法的优势在于:
- 自动确定簇数:无需预先指定簇数量
- 处理变密度数据:能同时识别不同密度的簇
- 鲁棒性:对噪声和异常值不敏感
- 层次化结果:提供不同粒度下的聚类视图
- 软聚类:提供簇成员概率而不仅是硬分配
这些特性使HDBSCAN特别适用于:
- 真实世界复杂数据集
- 探索性数据分析
- 异常检测
- 需要自动确定簇数的场景
通过本文的逐步解析,相信读者已经对HDBSCAN的工作原理有了深入理解。掌握这些原理有助于在实际应用中更好地使用和调参这一强大的聚类算法。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考