agglomerativeclustering默认只输出最终簇标签,不保存距离矩阵或合并顺序;需树状图或动态截断时应改用scipy.cluster.hierarchy.linkage。

AgglomerativeClustering 是 scikit-learn 中最常用的自底向上层次聚类实现,它不依赖距离矩阵预计算(默认用内存友好的树状结构),但必须提前指定簇数量 n_clusters——这是你最容易卡住的第一步。
为什么 fit() 后得不到距离矩阵或合并顺序?
AgglomerativeClustering 默认不保存完整的层次结构信息。它只输出每个样本的最终簇标签(labels_),不像 scipy.cluster.hierarchy.linkage 那样返回可用于画树状图的链接矩阵。
- 如果你需要树状图、动态截断簇数、或分析合并路径,别用
AgglomerativeClustering,改用scipy.cluster.hierarchy.linkage+dendrogram - 如果只需要固定簇数的硬划分(比如“把用户分成 5 类”),
AgglomerativeClustering更轻量、支持fit_predict流水线、且能用memory参数缓存中间结果 - 想绕过限制?可以手动传入预计算的
affinity='precomputed'和距离矩阵,再设compute_full_tree=True,但它仍不会暴露链接矩阵,只是内部多算一步
metric 和 linkage 的组合怎么选才不翻车?
metric 控制样本间距离,linkage 控制簇间距离,二者不匹配会导致反直觉结果。常见错误是:对高维稀疏数据用 euclidean + complete,结果所有点被拉成一条链。
-
linkage='ward'只接受metric='euclidean',且要求输入已中心化(否则会报ValueError: The ward clustering algorithm requires the data to be centered) - 文本或二值特征常用
metric='cosine'+linkage='average';single易受噪声拖拽,complete对离群点敏感 - 用
metric='precomputed'时,务必确认传入的是**对称、非负、对角为 0** 的方阵,否则fit()可能静默失败或聚出全零标签
如何让 AgglomerativeClustering 支持大数据量?
它本身不支持 mini-batch,时间复杂度是 O(n³),n 超过 10⁴ 就明显变慢。没有银弹,但有几条实操路径:
- 先用
KMeans或MiniBatchKMeans做粗粒度聚类(比如分 50 组),再对每组内部运行AgglomerativeClustering—— 这能降维+减样本量 - 用
sklearn.neighbors.NearestNeighbors提前剪枝:只计算每个点最近 k 个邻居的距离,构造稀疏距离矩阵,再喂给AgglomerativeClustering(affinity='precomputed') - 绝对不要在原始高维数据上直接跑;PCA 或 UMAP 降到 20–50 维后再聚,效果通常更好,且
linkage='ward'才真正可用
真正麻烦的不是调参,而是验证:层次聚类没有像轮廓系数那样普适的评估指标,尤其当真实簇数未知时,n_clusters 的选择往往得靠业务解释性反推——比如“这个簇里 70% 的用户都在凌晨下单”,比“轮廓系数提升了 0.02”有用得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











