层次凝聚聚类中linkage输出Z矩阵解读及聚类数-t关系图绘制
层次凝聚聚类:Z矩阵解读与聚类数-阈值关系图实现
一、linkage生成的Z矩阵含义
Z是形状为(n_samples-1, 4)的二维数组,每一行对应一次簇合并操作,各列具体含义:
- 第1、2列:当前合并的两个簇的ID。初始时每个样本是独立簇,ID从0到
n_samples-1;每次合并生成的新簇ID从n_samples开始依次递增(比如鸢尾花数据集共150个样本,第一个新簇ID为150) - 第3列:本次合并的两个簇之间的距离(即阈值t的临界值)
- 第4列:合并后新簇包含的样本总数
举个实例:若Z某一行是[10, 25, 0.8, 3],代表将ID为10和25的两个簇合并,二者距离为0.8,新簇包含3个样本。
二、生成(聚类数, 阈值t)对应值并绘图
每次簇合并会让总聚类数减少1,可利用Z矩阵的第三列(合并距离)生成所有关键阈值点,再计算对应聚类数:
实现代码
import seaborn as sns import scipy.cluster.hierarchy as sch import matplotlib.pyplot as plt from scipy.cluster.hierarchy import linkage, fcluster # 加载数据 iris = sns.load_dataset("iris") species = iris.pop("species") X = iris.values n_samples = X.shape[0] # 生成linkage矩阵 Z = linkage(X, 'ward') # 提取所有合并阈值(Z已按合并距离递增排列) merge_thresholds = Z[:, 2] # 生成对应聚类数:初始为样本总数,每次合并减1 cluster_counts = [n_samples - i for i in range(1, len(merge_thresholds)+1)] # 添加t趋近于0时的点(每个样本为独立簇) cluster_counts.insert(0, n_samples) merge_thresholds = [0] + list(merge_thresholds) # 绘制关系图 plt.figure(figsize=(10, 6)) plt.plot(merge_thresholds, cluster_counts, marker='o', linestyle='-', color='b') plt.xlabel('阈值t') plt.ylabel('聚类数') plt.title('聚类数与阈值t的关系') plt.grid(True) plt.show() # 输出关键对应值(示例:聚类数≤10的情况) print("关键(聚类数, 阈值t)对应值:") for cnt, t in zip(cluster_counts, merge_thresholds): if cnt <= 10: print(f"({cnt}, {round(t, 2)})")
补充说明
- 若需反推特定聚类数对应的阈值,可借助
fcluster或直接从Z矩阵提取:# 获取聚类数为3时的最小阈值 t_3 = Z[n_samples - 3 - 1, 2] print(f"聚类数为3时的阈值t约为:{round(t_3, 2)}")
内容的提问来源于stack exchange,提问作者Alexjandro Manjon
相关产品推荐
相关产品推荐

