OneMore插件终极指南:如何用免费工具彻底改变你的OneNote体验
2026/6/30 3:35:45
当你面对一堆看似杂乱无章的数据时,是否曾想过这些数据内部可能隐藏着某种层次结构?层次聚类算法正是解决这一问题的利器,而Scipy库中的dendrogram(树状图)则是展示这种层次结构的绝佳工具。本文将带你从基础概念出发,通过一个完整的案例,掌握如何使用Scipy的linkage和dendrogram函数来构建和解读层次聚类树状图。
层次聚类是一种无需预先指定聚类数量的无监督学习方法,它通过计算数据点之间的相似度(距离)来构建树形结构。与K-means等划分式聚类不同,层次聚类能够展示数据在不同粒度下的分组情况。
核心概念解析:
from scipy.cluster.hierarchy import linkage, dendrogram from matplotlib import pyplot as plt import numpy as np # 生成示例数据 np.random.seed(42) data = np.concatenate([ np.random.normal(loc=[0,0], scale=1, size=(50,2)), np.random.normal(loc=[5,5], scale=1, size=(50,2)) ]) # 计算连接矩阵 Z = linkage(data, method='ward')在应用层次聚类前,数据准备是至关重要的一步。不合适的预处理可能导致聚类结果失真。
关键预处理步骤:
数据清洗:
特征标准化:
距离度量选择:
from sklearn.preprocessing import StandardScaler # 标准化数据 scaler = StandardScaler() data_scaled = scaler.fit_transform(data) # 不同距离度量的效果对比 methods = ['euclidean', 'cityblock', 'cosine'] fig, axes = plt.subplots(1, 3, figsize=(18, 5)) for ax, metric in zip(axes, methods): Z = linkage(data_scaled, method='complete', metric=metric) dendrogram(Z, ax=ax) ax.set_title(f'Metric: {metric}') plt.tight_layout()树状图是层次聚类的可视化呈现,正确解读它需要理解几个关键元素:
树状图组成要素:
解读技巧:
plt.figure(figsize=(12, 6)) dendrogram(Z, truncate_mode='lastp', # 显示最后p个合并的簇 p=12, # 显示12个叶节点 show_leaf_counts=True, # 显示叶节点数量 leaf_rotation=90., # 旋转叶标签 leaf_font_size=12., # 叶标签字体大小 show_contracted=True) # 显示收缩的叶节点 plt.title('层次聚类树状图') plt.xlabel('样本索引或(簇大小)') plt.ylabel('距离') plt.axhline(y=5, c='k', linestyle='--') # 添加水平切割线 plt.show()Scipy的dendrogram函数提供了丰富的参数来控制树状图的显示效果和聚类行为。
关键参数详解:
| 参数 | 类型 | 描述 | 常用值 |
|---|---|---|---|
| p | int | 控制显示的簇数量 | 10-30 |
| truncate_mode | str | 截断模式 | 'lastp', 'level', None |
| color_threshold | float | 颜色区分阈值 | 0.7*max(Z[:,2]) |
| orientation | str | 树状图方向 | 'top', 'bottom', 'left', 'right' |
| labels | list | 叶节点标签 | 自定义标签列表 |
| leaf_rotation | float | 叶标签旋转角度 | 0-90 |
高级技巧:
# 自定义颜色阈值和标签 color_threshold = 0.7 * max(Z[:,2]) plt.figure(figsize=(15, 8)) dendrogram(Z, color_threshold=color_threshold, labels=[f'样本_{i}' for i in range(len(data))], leaf_label_func=lambda x: f'ID:{x}', above_threshold_color='grey') # 高于阈值的连接颜色 plt.title('带自定义颜色和标签的树状图') plt.show()让我们通过经典的鸢尾花数据集来展示层次聚类的完整流程。
from sklearn.datasets import load_iris # 加载数据 iris = load_iris() X = iris.data y = iris.target # 标准化并计算连接矩阵 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) Z = linkage(X_scaled, method='ward') # 绘制树状图 plt.figure(figsize=(12, 6)) dendrogram(Z, labels=y, orientation='right') plt.title('鸢尾花数据集层次聚类') plt.xlabel('距离') plt.ylabel('鸢尾花种类') plt.show() # 提取聚类结果 from scipy.cluster.hierarchy import fcluster clusters = fcluster(Z, t=3, criterion='maxclust') # 评估聚类效果 from sklearn.metrics import adjusted_rand_score print(f"调整兰德指数: {adjusted_rand_score(y, clusters):.3f}")结果分析:
在实际应用中,你可能会遇到以下典型问题:
问题1:大数据集导致树状图难以阅读
dendrogram(Z, truncate_mode='level', p=5)问题2:如何确定最佳聚类数量
from sklearn.metrics import silhouette_score # 尝试不同聚类数量 range_n_clusters = range(2, 10) silhouette_scores = [] for n_clusters in range_n_clusters: clusters = fcluster(Z, n_clusters, criterion='maxclust') silhouette_scores.append(silhouette_score(X_scaled, clusters)) plt.plot(range_n_clusters, silhouette_scores) plt.xlabel('聚类数量') plt.ylabel('轮廓系数') plt.show()问题3:处理高维数据
from sklearn.decomposition import PCA pca = PCA(n_components=2) X_pca = pca.fit_transform(X_scaled) Z_pca = linkage(X_pca, method='ward')层次聚类并非适用于所有场景,了解其优缺点有助于做出正确选择:
对比表格:
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 层次聚类 | 可视化直观,无需预设K值 | 计算复杂度高(O(n³)) | 中小数据集,需要层次关系 |
| K-means | 计算效率高(O(n)) | 需要预设K值,对异常值敏感 | 大数据集,球形簇 |
| DBSCAN | 能发现任意形状簇,抗噪声 | 参数敏感,高维效果差 | 非凸形状,含噪声数据 |
选择建议:
# 对比K-means和层次聚类 from sklearn.cluster import KMeans kmeans = KMeans(n_clusters=3) kmeans_labels = kmeans.fit_predict(X_scaled) hierarchical_labels = fcluster(Z, 3, criterion='maxclust') fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) ax1.scatter(X[:,0], X[:,1], c=kmeans_labels) ax1.set_title('K-means聚类') ax2.scatter(X[:,0], X[:,1], c=hierarchical_labels) ax2.set_title('层次聚类') plt.show()在实际项目中,我经常发现层次聚类在探索性分析阶段特别有价值。它提供的树状图不仅能展示最终聚类结果,还能揭示数据在不同尺度下的组织结构,这是其他聚类方法难以替代的。当处理基因表达数据时,通过调整颜色阈值和切割高度,往往能发现意想不到的生物标记物组合。