TL;DR
场景:用 sklearn 做 KMeans 聚类,想解释中心点/损失,并用指标选 K。
结论:inertia_ 只能”越小越好但不可比”,选 K 更应看 -silhouette_score 的峰值;代码里要修正 idxmin/变量名混用。
产出:一套可复用的”属性解读 + 选 K 曲线 + 版本差异 + 报错排查”模板。
sklearn实现 K-Means
cluster.cluster_centers_
centroid = cluster.cluster_centers_
centroid
centroid.shape
cluster.inertia_
查看总距离的平方和:
inertia = cluster.inertia_
inertia
如果我们把簇的数量换成 4,Inertia 会怎么样?
n_clusters = 4
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
如果换成 5:
n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_
inertia_
聚类算法模型评估:轮廓系数
不同于分类模型和回归,聚类算法的模型评估不是一件简单的事。聚类算法的模型评估是聚类分析中最重要的环节之一。
如何衡量聚类算法的效果
聚类模型的结果不是某种标签输出,并且聚类的结果是不确定的,其优劣由业务需求或算法需求来决定。我们使用轮廓系数来衡量聚类的效果。
轮廓系数
轮廓系数是对每个样本来定义的,它能够同时衡量:
- 样本与其自身所在的簇中的其他样本的相似度 a,等于样本与同一簇所有其他点之间的平均距离
- 样本与其他簇中的样本相似度 b ,等于样本与下一个最近的簇中的所有点之间的平均距离
单个样本的轮廓系数为:
s = (b - a) / max(a, b)
轮廓系数范围是(-1,1):
- 轮廓系数越接近 1:样本与自己所在簇中的样本很相似,并且与其他簇中的样本不相似
- 轮廓系数为 0 时,两个簇中的样本相似度一致,两个簇本应该是一个簇
- 轮廓为负时:样本点与簇外的样本更相似
sklearn 轮廓系数
from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
# 计算所有样本的轮廓系数均值
silhouette_score(X, cluster.labels_)
# 计算每个样本的轮廓系数
silhouette_samples(X, cluster.labels_)
观察不同 K 下的轮廓系数
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
# 定义存储评分的列表
score = []
# 进行 KMeans 聚类并计算 silhouette_score
for i in range(2, 100):
cluster = KMeans(n_clusters=i, random_state=0).fit(X)
score.append(silhouette_score(X, cluster.labels_))
# 绘制 silhouette_score 的变化曲线
plt.plot(range(2, 100), score)
# 找到 silhouette_score 最小值对应的索引,并绘制一条垂直线
plt.axvline(pd.DataFrame(score).idxmin()[0] + 2, ls=':')
plt.title('Silhouette Score vs Number of Clusters')
plt.xlabel('Number of Clusters')
plt.ylabel('Silhouette Score')
plt.show()
错误速查
| 症状 | 根因 | 修复 |
|---|---|---|
| 运行 silhouette_score 报错或结果异常 | 变量混用:cluster 与 cluster_ 不一致 | 统一变量名 |
| 选 K 画线落在”最差点”而不是”最好点” | 用了 idxmin() | 改为 idxmax() |
| 同一份数据在不同机器/版本下结果不一致 | sklearn 1.4 起 n_init 默认 ‘auto’ | 显式指定 n_init、init、random_state |
| inertia 很大、肘部不明显 | 特征未标准化/量纲差异大 | 先做标准化/归一化 |
| silhouette_score 计算很慢 | K 扫描范围过大 | 缩小 K 搜索区间 |
| silhouette 出现大量负值 | K 不合适/簇重叠严重 | 调整 K、换特征工程 |