📢 转载信息
原文链接:https://machinelearningmastery.com/k-means-cluster-evaluation-with-silhouette-analysis/
原文作者:Jason Brownlee
K-均值(K-means)聚类是一种流行的无监督学习算法,用于将数据点分组到预定义的 K 个簇中。选择正确的 K 值是 K-均值算法的关键挑战之一。本文将介绍一种用于评估 K-均值聚类有效性的技术,即使用轮廓分析(Silhouette Analysis)。
什么是轮廓分析?
轮廓分析是一种用于评估聚类质量的技术。它量化了数据点与其自身簇内的样本的相似度,以及与其他最近邻簇的样本的差异度。轮廓系数(Silhouette Coefficient)的取值范围是 -1 到 +1。
轮廓系数的计算公式如下:
$$ s(i) = \frac{b(i) - a(i)}{\max\{a(i), b(i)\} } $$
其中:
-
a(i) 是数据点 i 与其自身簇中的所有其他点之间的平均距离(即簇内距离)。
-
b(i) 是数据点 i 与其最近邻簇(即距离最近的另一个簇)中所有点的最小平均距离(即簇间距离)。
轮廓系数的解释如下:
-
如果 s(i) 接近 +1,则表示数据点 i 与其自身簇匹配良好,并且与其他簇分离良好。这表明聚类效果很好。
-
如果 s(i) 接近 0,则表示数据点 i 位于两个相邻簇的边界上,聚类效果不佳。
-
如果 s(i) 接近 -1,则表示数据点 i 可能被错误地分配给了当前的簇,它更适合于相邻的簇。
如何使用轮廓分析?
轮廓分析的主要目的是帮助我们确定最佳的簇数量 K。
轮廓分析的常用步骤是:
-
在给定的数据集上,对一系列不同的 K 值(例如,从 2 到 10)运行 K-均值聚类。
-
为每个 K 值计算所有数据点的平均轮廓系数。
-
选择具有最高平均轮廓系数的 K 值。
此外,还可以绘制轮廓图(Silhouette Plot),以更详细地了解每个簇的质量。
轮廓图的结构
轮廓图可视化了每个数据点的轮廓系数,并按簇分组。通常,轮廓图的结构如下:
-
图的垂直线表示所有数据点的平均轮廓系数。
-
每个簇由一组形状相似的条形表示,每个条形代表一个数据点的轮廓系数。
-
如果所有簇的条形都位于平均线左侧或非常靠近平均线,则表示簇分离不佳或重叠。
-
理想情况下,我们希望看到簇的条形都明显大于平均线,并且每个簇的厚度相对一致,表明簇的大小和密度相对均衡。
K-均值轮廓分析的Python实现
我们可以使用 Scikit-learn 库来实现 K-均值聚类和轮廓分析。
首先,我们需要导入必要的库并准备数据。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, silhouette_samples
# 1. 生成示例数据集
X, y = make_blobs(n_samples=500, n_features=2, centers=4, cluster_std=1, random_state=42)
然后,我们可以遍历不同的 K 值并计算平均轮廓系数。
# 2. 遍历 K 值并计算轮廓系数
range_n_clusters = [2, 3, 4, 5, 6]
avg_silhouette_scores = []
for n_clusters in range_n_clusters:
# 运行 K-均值
clusterer = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
cluster_labels = clusterer.fit_predict(X)
# 计算平均轮廓系数
silhouette_avg = silhouette_score(X, cluster_labels)
avg_silhouette_scores.append(silhouette_avg)
print(f"对于 n_clusters = {n_clusters}, 平均轮廓系数为: {silhouette_avg:.4f}")
# 3. 找到最佳 K 值
optimal_k = range_n_clusters[np.argmax(avg_silhouette_scores)]
print(f"\n最佳 K 值为: {optimal_k}")
为了更直观地理解,我们可以绘制轮廓图。
# 4. 绘制轮廓图
plt.figure(figsize=(10, 8))
for i, n_clusters in enumerate(range_n_clusters):
plt.subplot(3, 2, i + 1)
# 运行 K-均值
clusterer = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
cluster_labels = clusterer.fit_predict(X)
# 计算轮廓分数和样本分数
silhouette_avg = silhouette_score(X, cluster_labels)
sample_silhouette_values = silhouette_samples(X, cluster_labels)
y_lower = 10
for j in range(n_clusters):
# 收集簇 j 的轮廓分数
ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == j]
ith_cluster_silhouette_values.sort()
color = plt.cm.Spectral(float(j) / n_clusters)
plt.fill_betweenx(np.arange(y_lower, y_lower + ith_cluster_silhouette_values.shape[0]),
0, ith_cluster_silhouette_values,
facecolor=color,
edgecolor=color,
alpha=0.7)
# 标记簇 j 的轮廓系数的平均值
plt.text(-0.05, y_lower + 0.5 * ith_cluster_silhouette_values.shape[0], str(j))
# 计算下一个簇的起始位置
y_lower += ith_cluster_silhouette_values.shape[0] + 2
plt.title(f"K={n_clusters} 的轮廓图")
plt.xlabel("轮廓系数值")
plt.ylabel("簇索引")
# 绘制平均轮廓线
plt.axvline(x=silhouette_avg, color="red", linestyle="--")
plt.text(0.05, 0.95, f'Avg Score: {silhouette_avg:.2f}', transform=plt.gca().transAxes, fontsize=10, verticalalignment='top')
plt.yticks([]) # 隐藏 Y 轴标签
plt.tight_layout()
plt.show()
在上面的输出中,我们可以比较不同 K 值的平均轮廓系数。通常,最高平均轮廓系数对应的 K 值是最佳选择。同时,观察轮廓图可以帮助我们确认簇的质量和分离度。
总结
轮廓分析提供了一种强大的、基于距离的指标来评估 K-均值聚类的结果。通过观察平均轮廓系数和轮廓图,数据科学家可以更科学地确定数据集中的自然簇数 K,从而提高聚类模型的有效性。尽管轮廓分析是一个有用的工具,但最好结合其他方法(如肘部法则)进行综合判断。
🚀 想要体验更好更全面的AI调用?
欢迎使用青云聚合API,约为官网价格的十分之一,支持300+全球最新模型,以及全球各种生图生视频模型,无需翻墙高速稳定,文档丰富,小白也可以简单操作。
评论区