别再只盯着K-Means了!用sklearn的轮廓系数(silhouette_score)帮你选出最佳聚类算法

张开发
2026/4/19 23:36:08 15 分钟阅读

分享文章

别再只盯着K-Means了!用sklearn的轮廓系数(silhouette_score)帮你选出最佳聚类算法
用轮廓系数为聚类算法打分从K-Means到DBSCAN的科学选择指南当面对一堆未标注的数据时很多人的第一反应是直接套用K-Means算法——这就像拿到食材只会做炒饭一样。但真实世界的数据分布千奇百怪有的像瑞士奶酪布满空洞适合DBSCAN有的像俄罗斯套娃层层嵌套适合层次聚类而K-Means只擅长处理那些团状分布的数据。本文将带你用sklearn的轮廓系数这把尺子量化评估不同聚类算法的表现用数据而非直觉做决策。1. 为什么需要轮廓系数去年我们团队处理用户行为数据时曾用K-Means强行将用户分成5个群体。上线后发现营销效果极差——原来算法把活跃用户和羊毛党混在了一起。后来用轮廓系数评估才发现这个数据集用谱聚类效果更好。这个教训告诉我们没有最好的算法只有最适合的评估方法。轮廓系数的精妙之处在于它同时考虑了两个维度凝聚度a(i)同簇样本间的紧密程度分离度b(i)样本与其他簇的疏远程度计算公式为s(i) (b(i) - a(i)) / max(a(i), b(i))这个值域在-1到1之间的指标能直观反映聚类质量分数区间含义实际问题0.7-1.0聚类效果优秀-0.5-0.7结构清晰但有待优化可能需要调整超参数0.3-0.5聚类结果勉强可用建议尝试其他算法0.3聚类效果不可信数据可能不适合聚类注意轮廓系数对凸形簇更敏感。当数据存在复杂流形结构时建议结合Calinski-Harabasz指数等指标综合评估2. 实战对比三大聚类算法让我们用经典的鸢尾花数据集演示如何科学选择算法。首先加载数据并预处理from sklearn.datasets import load_iris from sklearn.preprocessing import StandardScaler iris load_iris() X StandardScaler().fit_transform(iris.data)2.1 K-Means的局限与突破默认情况下人们会用肘部法则确定K值from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score k_range range(2, 8) scores [] for k in k_range: kmeans KMeans(n_clustersk, random_state42) labels kmeans.fit_predict(X) scores.append(silhouette_score(X, labels))结果可能让你惊讶K值轮廓系数20.5830.4640.3950.35虽然真实类别数是3但K2时轮廓系数反而更高——这说明数据本身可能存在层级结构单纯增加簇数反而破坏自然分组。2.2 DBSCAN的密度魔法对于密度不均的数据试试DBSCANfrom sklearn.cluster import DBSCAN eps_values [0.3, 0.5, 0.7] min_samples [3, 5, 7] results [] for eps in eps_values: for min_s in min_samples: dbscan DBSCAN(epseps, min_samplesmin_s) labels dbscan.fit_predict(X) if len(set(labels)) 1: # 排除所有样本归为一类的情况 score silhouette_score(X, labels) results.append((eps, min_s, score))最佳参数组合可能产生0.62的轮廓系数比K-Means更优。但要注意当eps过大时所有样本会被归为同一类轮廓系数无效数据需要标准化否则密度计算会被量纲影响2.3 层次聚类的嵌套优势对于层级结构明显的数据层次聚类是更好的选择from sklearn.cluster import AgglomerativeClustering linkage [ward, complete, average] scores [] for link in linkage: agg AgglomerativeClustering(n_clusters3, linkagelink) labels agg.fit_predict(X) scores.append(silhouette_score(X, labels))结果对比连接方式轮廓系数特点ward0.51适合欧式空间complete0.49对异常值鲁棒average0.53平衡各维度影响3. 高级技巧与避坑指南3.1 样本级诊断工具silhouette_samples能定位问题样本from sklearn.metrics import silhouette_samples import numpy as np sample_scores silhouette_samples(X, labels) problem_samples np.where(sample_scores 0)[0] # 找出分配错误的样本我曾用这个方法发现某电商数据中高消费低频用户总是被错误归类。后来发现需要先对购买频率和金额做对数变换。3.2 可视化决策结合轮廓分析图更直观import matplotlib.pyplot as plt from sklearn.metrics import silhouette_samples def plot_silhouette(X, labels): n_clusters len(set(labels)) sample_scores silhouette_samples(X, labels) fig, ax plt.subplots(figsize(8, 6)) y_lower 10 for i in range(n_clusters): ith_cluster_scores sample_scores[labels i] ith_cluster_scores.sort() size ith_cluster_scores.shape[0] y_upper y_lower size ax.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_scores, alpha0.7) ax.text(-0.05, y_lower 0.5 * size, str(i)) y_lower y_upper 10 ax.set_xlabel(Silhouette coefficient values) ax.set_ylabel(Cluster label) ax.axvline(xnp.mean(sample_scores), colorred, linestyle--)3.3 特殊数据结构的处理当遇到以下情况时需要特别处理高维数据先使用PCA降维再计算轮廓系数from sklearn.decomposition import PCA X_pca PCA(n_components0.95).fit_transform(X)非欧式数据改用适合的metric# 对于文本数据使用余弦相似度 silhouette_score(X, labels, metriccosine)超大样本量使用sample_size参数silhouette_score(X, labels, sample_size1000, random_state42)4. 超越轮廓系数多维度评估框架虽然轮廓系数很强大但明智的数据科学家会建立综合评估体系稳定性检验通过bootstrap采样观察聚类结果波动from sklearn.utils import resample stability_scores [] for _ in range(10): X_resampled resample(X) labels model.fit_predict(X_resampled) stability_scores.append(silhouette_score(X_resampled, labels))业务指标验证将聚类结果与业务KPI关联用户分群后的留存率差异商品类别的购买转化率算法组合策略先用DBSCAN去除噪声点再用K-Means聚类核心样本最后用轮廓系数评估混合效果在实际项目中我发现这样的组合往往能提升15-20%的轮廓系数。特别是在处理地理位置数据时先用DBSCAN识别城市中心区域再用K-Means细分商圈效果比单一算法好得多。

更多文章