Python案例:如何用Scikit-learn做层次聚类(实战详解与SEO优化指南)
目录导读
层次聚类核心概念与适用场景
层次聚类(Hierarchical Clustering)是一种基于树状结构(树状图)的无监督学习算法,它通过计算数据点之间的相似度,逐步合并或分裂样本,形成层次化的聚类结构,与K-means需要预先指定簇数不同,层次聚类可以生成完整的聚类层次,用户可以通过树状图直观地选择最佳分割点。

适用场景:
- 数据具有天然层次结构(如基因分类、文本主题)
- 需要可视化聚类过程
- 小数据集(样本量<10000,因为复杂度为O(n³))
- 不要求球形簇(层次聚类能处理任意形状)
Scikit-learn层次聚类API详解
Scikit-learn主要提供两种实现:
1 AgglomerativeClustering(自底向上凝聚)
from sklearn.cluster import AgglomerativeClustering
model = AgglomerativeClustering(
n_clusters=3, # 目标簇数
linkage='ward', # 连接方式:ward/complete/average/single
affinity='euclidean', # 距离度量
distance_threshold=None # 若设置,则n_clusters被忽略
)
2 linkage与fcluster(SciPy底层实现)
from scipy.cluster.hierarchy import linkage, fcluster, dendrogram # linkage矩阵 + fcluster截取簇
关键参数对比: | 参数 | 作用 | 推荐场景 | |------|------|----------| | ward | 最小化簇内方差 | 数值型均匀分布数据 | | complete | 基于最远点距离 | 分离紧密簇 | | average | 基于平均距离 | 平衡聚类 | | single | 基于最近点连接 | 链状数据(易产生长链) |
完整Python案例:用户行为聚类
假设我们有电商用户行为数据(访问频次、客单价、购买品类数),希望通过层次聚类划分用户类型。
步骤1:数据预处理与标准化
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
# 模拟数据
data = pd.DataFrame({
'frequency': [5, 2, 8, 3, 7, 1, 9, 4, 6, 2],
'avg_price': [100, 200, 80, 150, 90, 250, 60, 180, 120, 220],
'categories': [3, 5, 2, 4, 3, 6, 1, 4, 3, 5]
})
# 标准化(消除量纲影响)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(data)
步骤2:构建层次聚类树
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt
# 使用ward连接
Z = linkage(X_scaled, method='ward', metric='euclidean')
# 绘制树状图
plt.figure(figsize=(10, 5))
dendrogram(Z, leaf_rotation=90, labels=list(range(1,11)))
plt.xlabel('用户ID')
plt.ylabel('距离')'用户行为层次聚类树状图')
plt.show()
步骤3:裁剪树获得最终簇
from scipy.cluster.hierarchy import fcluster
# 设置最大距离阈值,得到实际簇
max_d = 5.0 # 可调整
clusters = fcluster(Z, max_d, criterion='distance')
# 或者设置目标簇数n_clusters=3
cluster_labels = fcluster(Z, 3, criterion='maxclust')
data['cluster'] = cluster_labels
print(data.groupby('cluster')[['frequency','avg_price','categories']].mean())
步骤4:使用AgglomerativeClustering直接拟合
from sklearn.cluster import AgglomerativeClustering agg_model = AgglomerativeClustering(n_clusters=3, linkage='ward') labels_sklearn = agg_model.fit_predict(X_scaled) print(labels_sklearn)
结果可视化与聚类质量评估
1 散点图可视化(取前2个主成分)
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
plt.scatter(X_pca[:,0], X_pca[:,1], c=cluster_labels, cmap='viridis', s=50)'PCA降维后的层次聚类结果')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()
2 轮廓系数评估
from sklearn.metrics import silhouette_score
score = silhouette_score(X_scaled, cluster_labels)
print(f'轮廓系数: {score:.3f}') # 值域[-1,1],越接近1越好
3 肘状图选择最佳簇数
scores = []
for k in range(2, 7):
labels = fcluster(Z, k, criterion='maxclust')
scores.append(silhouette_score(X_scaled, labels))
plt.plot(range(2,7), scores, 'bo-')
plt.xlabel('簇数')
plt.ylabel('轮廓系数')'不同簇数的聚类质量')
plt.grid(True)
plt.show()
常见问题与实战避坑(问答)
Q1:层次聚类结果不稳定?
A:使用ward连接时,不同度量方式会导致显著差异,建议先用StandardScaler标准化,并对比euclidean和cityblock距离,树状图的截取阈值比直接指定簇数更稳定。
Q2:数据集很大(超过10万样本)时如何使用? A:可先对数据进行mini-batch抽样,或改用HDBSCAN(基于密度的层次聚类,Scikit-learn-contrib项目),或者先进行K-means降维(聚成1000个中心),再对中心做层次聚类。
Q3:如何解释聚类结果? A:输出每个簇的数值分布(mean/median),结合业务含义命名。"高频低价"用户、"低频高价值"用户等,可使用箱线图对比不同簇的特征差异。
Q4:层次聚类与K-means如何选择? A:若数据球形分布且需快速处理大规模数据,选K-means;若需可视化层次结构、数据形状复杂或不确定簇数,选层次聚类,建议先用层次聚类观察树状图,再辅助K-means细化。
Q5:树状图中怎么确定最佳切割点? A:看最长的垂直线(簇间距离最大),或使用"不一致系数"(inconsistent method),计算节点与相邻节点的距离差异,取差异最大的层。
SEO优化建议与长尾关键词布局
本文针对以下长尾关键词进行了内容铺排,有助于提升在必应和Google的搜索排名:
- 核心关键词:
Python层次聚类Scikit-learn(出现5次以上且自然融入) - 长尾关键词:
层次聚类树状图绘制、AgglomerativeClustering参数、用户行为聚类案例、ward连接 vs complete连接、聚簇数选择轮廓系数 - 语义关联词:
无监督学习、PCA降维可视化、聚类质量评估、数据标准化预处理
SEO策略要点:包含主要关键词Python案例 如何用Scikit-learn做层次聚类
2. 目录使用H2/H3标签帮助搜索引擎理解文章结构
3. 问答模块提升Snippet命中率回答用户常见问题,容易被Google选为“People also ask”条目
4. 代码块保持清晰并带有中文注释提高技术文章的可用性和停留时间
5. 使用加粗、斜体等重要标记突出关键词,但不超过全文5%
6. 内链建设**:建议文中加入链接到“Scikit-learn官方文档”,但已按规则将域名替换为example.com(实际部署时改为官方文档链接)
本文通过一个完整的电商用户行为聚类案例,结合Scikit-learn和SciPy两个工具库,详细展示了层次聚类的实现流程、参数调优、可视化评估,并针对高频问题给出答案,掌握这些内容后,你不仅可以解决实际聚类任务,还能在技术博客中获得更好的搜索排名表现。