50·无监督学习进阶

层次聚类

clusteringunsupervised

第 50 课 - 层次聚类

学习目标

学完本课,你将能够:

  1. 理解层次聚类的基本概念及其两种主要类型(凝聚与分裂)。
  2. 掌握凝聚层次聚类(Agglomerative Clustering)的核心步骤、关键参数(如链接准则)。
  3. 学会解读聚类树状图,并根据业务需求选择合适的聚类结果。
  4. 使用 scikit-learn 库在Python中实现层次聚类,并应用于实际数据集。
  5. 对比层次聚类与K-Means聚类的优缺点。

核心概念

层次聚类(Hierarchical Clustering)是一种通过构建聚类层次结构(树状图)来进行聚类的方法。与K-Means需要预先指定簇数K不同,层次聚类能生成一个包含所有可能簇数(从1个到样本数N个)的树状图,供我们“横切”以选择最合适的划分。

1. 凝聚层次聚类(自底向上)

这是最常用的层次聚类方法,过程非常直观:

  • 初始状态:将每个数据点都看作一个独立的簇。
  • 迭代合并:每一步,找到距离最近的两个簇,将它们合并为一个新簇。
  • 终止条件:重复合并步骤,直到所有点都在一个簇中,或达到预设的簇数。

关键:如何定义“距离最近的两个簇”? 这由链接准则(Linkage Criteria) 决定:

  • 单链接(Single Linkage):两个簇中最近的两个点之间的距离。容易产生“链状”簇。
  • 全链接(Complete Linkage):两个簇中最远的两个点之间的距离。倾向于产生紧凑的球形簇。
  • 平均链接(Average Linkage):两个簇中所有点对之间距离的平均值。介于前两者之间。
  • 沃德链接(Ward Linkage):合并后导致的总类内方差增量最小。倾向于产生大小相近的簇,常用于方差分析。

2. 树状图(Dendrogram)

树状图是层次聚类的可视化输出,它像一棵倒置的树。

  • 叶节点:代表原始数据点。
  • 合并高度:横线代表一次合并,其高度(纵轴)表示被合并的两个簇之间的距离(由链接准则定义)。
  • “剪切”树状图:在某个高度水平画一条横线,横线与所有竖线的交点数,就是此时的簇数。聚类的本质就是选择在哪里“剪切”这棵树

代码示例

下面是一个完整的层次聚类示例,包括数据生成、聚类、树状图绘制和结果可视化。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.datasets import make_blobs

# 1. 生成模拟数据
X, y_true = make_blobs(n_samples=150, centers=4, cluster_std=0.8, random_state=42)

# 2. 使用凝聚层次聚类 (Ward链接)
# n_clusters参数表示我们希望最终得到的簇数
agg_clustering = AgglomerativeClustering(n_clusters=4, linkage='ward')
y_pred = agg_clustering.fit_predict(X)

# 3. 绘制聚类结果散点图
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis', edgecolor='k', s=50)
plt.title('Hierarchical Clustering Results (Ward Linkage)')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')

# 4. 绘制树状图
# 使用scipy的linkage函数计算层次聚类的合并过程
Z = linkage(X, method='ward')
plt.subplot(1, 2, 2)
dendrogram(Z, truncate_mode='lastp', p=20, leaf_rotation=90., leaf_font_size=12.)
plt.title('Dendrogram (Ward Linkage)')
plt.xlabel('Sample Index or (Cluster Size)')
plt.ylabel('Distance')
plt.axhline(y=15, color='r', linestyle='--', label='Cut for 4 clusters') # 示意剪切线
plt.legend()
plt.tight_layout()
plt.show()

print("预测的簇标签 (前10个):", y_pred[:10])

代码解读

  1. 我们使用AgglomerativeClustering类,指定了n_clusters=4linkage='ward'
  2. fit_predict方法直接给出每个样本的簇标签。
  3. 树状图由scipy.cluster.hierarchy模块绘制,它展示了完整的合并历史。图中红色虚线是一个示意性的“剪切”线,它与树干相交4次,对应4个簇。

实践练习

练习1:探索链接准则

使用上面的相同数据集X,分别用'single''complete'‘average'链接准则进行聚类(簇数设为4)。并排绘制三个聚类结果的散点图(使用subplot),比较它们的形状有何不同。

预期输出:三张子图,显示三种链接准则下不同的聚类边界和形状。

练习2:解读与选择

观察本课代码生成的“树状图”。如果我们将红色虚线向上移动(增大距离阈值),聚类结果会如何变化(簇数增加还是减少)?请解释原因。

练习3:实战应用

加载sklearn自带的iris数据集(共150个样本,3类)。对其特征进行标准化(StandardScaler),然后使用Ward链接准则进行层次聚类。

  1. 你觉得应该选择几个簇?请通过观察树状图来支持你的观点。
  2. 将聚类结果(3个簇)与真实的品种标签y进行比较,计算准确率(注意:聚类标签是任意的,你需要尝试不同的标签映射方式来获得最佳匹配)。

常见错误

  1. 误解树状图的“剪切”位置:在树状图上随意画一条横线而不考虑距离轴的实际意义。正确做法:应观察距离的较大“跳跃”或结合业务需求(如需要多少个细分市场)来确定剪切高度。
  2. 盲目选择链接准则:没有根据数据分布和业务目标选择链接准则。例如,如果数据中有链状结构,使用Ward链接可能效果不佳;如果希望簇大小均衡,单链接可能不是好选择。
  3. 忘记数据标准化:层次聚类(特别是使用欧氏距离的Ward链接)对特征的尺度敏感。如果一个特征的范围是0-1000,另一个是0-1,聚类将严重受前者主导。务必在聚类前对数据进行标准化(StandardScaler
  4. 计算复杂度问题:层次聚类的计算和存储复杂度通常为O(n²)或O(n³),对于大数据集(如n > 10000)可能非常慢且消耗大量内存。此时应考虑使用K-Means或Mini-Batch K-Means等更高效的算法。

小结

  • 层次聚类的核心是构建一个簇的层次结构(树状图),提供了从单个点到单个簇的完整聚类视图。
  • 凝聚层次聚类是自底向上合并的过程,其关键参数是链接准则(Ward、Complete、Average、Single),它决定了如何衡量两个簇之间的“距离”。
  • 树状图是理解和解释层次聚类结果的最重要工具,通过在不同高度“剪切”树状图,可以获得不同粒度的聚类结果。
  • 与K-Means对比:层次聚类无需预先指定簇数,能提供丰富的结构信息,但计算开销更大;K-Means速度快、可伸缩性强,但必须指定K且对初始中心敏感。
  • 适用场景:层次聚类适用于数据量中等、希望探索数据内在层次结构、或不确定簇数的情况。常用于生物信息学(基因/物种分类)、市场细分、文档聚类等领域。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「DBSCAN 密度聚类」 以巩固所学知识。