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、换特征工程