在机器学习领域,聚类算法是一种无监督学习方法,旨在将数据集中的样本划分为若干个簇,使得同一簇内的样本相似度高,而不同簇之间的样本相似度低。K均值聚类算法是其中一种常用的聚类方法,它通过迭代优化簇中心点来实现数据的聚类。然而,K均值聚类算法的一个关键问题是确定最优的簇数量,即如何选择合适的k值。轮廓分析提供了一种评估不同k值的方法,它通过计算轮廓系数来衡量样本点与其邻近簇的距离,从而帮助选择最佳的簇数量。
轮廓系数的取值范围在-1到1之间,接近1的值表示样本点远离邻近簇,0表示样本点位于两个邻近簇的决策边界上,而负值则可能表示样本点被错误地分配到了某个簇中。在本例中,使用轮廓分析来选择最优的簇数量。轮廓图显示,当簇数量为3、5和6时,由于存在轮廓分数低于平均值的簇以及轮廓图大小的大幅波动,这些簇数量的选择对于给定数据来说并不理想。轮廓分析在决定2和4之间的簇数量时更为模糊。
此外,通过轮廓图的厚度可以直观地观察到簇的大小。当簇数量为2时,轮廓图的大小较大,这是因为将3个子簇合并为一个大簇。然而,当簇数量为4时,所有的轮廓图大小大致相同,因此簇的大小也大致相同,这一点也可以从右侧标记的散点图中得到验证。
以下是不同簇数量下的平均轮廓分数:
For n_clusters = 2 The average silhouette_score is : 0.7049787496083262
For n_clusters = 3 The average silhouette_score is : 0.5882004012129721
For n_clusters = 4 The average silhouette_score is : 0.6505186632729437
For n_clusters = 5 The average silhouette_score is : 0.561464362648773
For n_clusters = 6 The average silhouette_score is : 0.4857596147013469
为了实现这一分析,首先使用make_blobs函数生成样本数据。这个特定的设置有一个明显的簇和3个紧密放置的簇。然后,为不同的簇数量创建子图,包括轮廓图和实际聚类形成的散点图。在轮廓图中,计算了每个样本的轮廓分数,并根据它们所属的簇对这些分数进行聚合和排序。使用不同的颜色来表示不同的簇,并在轮廓图上绘制了平均轮廓分数的垂直线。在散点图中,使用不同的颜色来表示不同的簇,并在簇中心处绘制了白色的圆圈。
以下是实现轮廓分析的Python代码示例:
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import silhouette_samples, silhouette_score
# 生成样本数据
X, y = make_blobs(n_samples=500, n_features=2, centers=4, cluster_std=1, center_box=(-10.0, 10.0), shuffle=True, random_state=1)
# 定义不同的簇数量
range_n_clusters = [2, 3, 4, 5, 6]
for n_clusters in range_n_clusters:
# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 7))
# 计算轮廓分数
clusterer = KMeans(n_clusters=n_clusters, random_state=10)
cluster_labels = clusterer.fit_predict(X)
silhouette_avg = silhouette_score(X, cluster_labels)
print("For n_clusters =", n_clusters, "The average silhouette_score is :", silhouette_avg)
# 计算每个样本的轮廓分数
sample_silhouette_values = silhouette_samples(X, cluster_labels)
# 绘制轮廓图
y_lower = 10
for i in range(n_clusters):
ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
ith_cluster_silhouette_values.sort()
size_cluster_i = ith_cluster_silhouette_values.shape[0]
y_upper = y_lower + size_cluster_i
color = cm.nipy_spectral(float(i) / n_clusters)
ax1.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_silhouette_values, facecolor=color, edgecolor=color, alpha=0.7)
ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
y_lower = y_upper + 10
# 设置轮廓图的标题和标签
ax1.set_title("The silhouette plot for the various clusters.")
ax1.set_xlabel("The silhouette coefficient values")
ax1.set_ylabel("Cluster label")
ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
ax1.set_yticks([])
ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
# 绘制散点图
colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
ax2.scatter(X[:, 0], X[:, 1], marker=".", s=30, lw=0, alpha=0.7, c=colors, edgecolor="k")
centers = clusterer.cluster_centers_
ax2.scatter(centers[:, 0], centers[:, 1], marker="o", c="white", alpha=1, s=200, edgecolor="k")
for i, c in enumerate(centers):
ax2.scatter(c[0], c[1], marker="$%d$" % i, alpha=1, s=50, edgecolor="k")
# 设置散点图的标题和标签
ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")
plt.suptitle("Silhouette analysis for KMeans clustering on sample data with n_clusters = %d" % n_clusters, fontsize=14, fontweight="bold")
plt.show()