📜  KMeans 中 k 最优值的肘部方法(1)

📅  最后修改于: 2023-12-03 14:43:40.183000             🧑  作者: Mango

KMeans 中 k 最优值的肘部方法

在进行聚类分析时,KMeans 是其中一个通用的方法。但是,对于 KMeans,如何确定最佳的聚类数量 k,是一个常见的问题。

在实际问题中,往往需要通过实验得出最优的聚类数量。其中,肘部方法就是一种被广泛采用的确定最佳聚类数量的方法之一。

肘部方法

肘部方法,也称为“肘部图法”,是一种图形化解决聚类数量(k)选择问题的方法。它的基本思想是计算多个 k 值下各自聚类的评估指标,并作图显示这些指标随 k 值的变化趋势。通常情况下,这种变化趋势会呈现出一个类似于手肘弯曲的形状,因为随着聚类数 k 增加,每个聚类内部的离群点数量越来越少,同一聚类内部的数据元素越来越有可比性。当选择的聚类数 k 达到一个臂弯曲结束的位置时,进一步增加 k 得到的收益会不断降低,并且约束不足之处开始显露。

具体来说,它如下图所示:

肘部方法

在图中可以看到,随着聚类数量 k 的增加,SSE(Sum of Squared Errors)开始减少,但随着 k 的增加,SSE 的增减幅度逐渐变小。当 k 达到 3 时,SSE 的增幅开始变缓,此时的点即是所谓的“肘部”,再增加 k 收益开始变得小,我们可以选择肘部对应的聚类数量作为最终的结果。

实现

对于 KMeans,它的 Python 实现可以在 sklearn 中找到。下面是一个实现肘部方法的例子:

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist
import numpy as np

# 生成随机的测试数据
X = np.random.uniform(size=(100,2))

# 最大聚类数量
K = 10

# 聚类数量遍历范围
ks = range(1,K+1)

# 存储每个 k 下的 SSE
SSE = []

# 计算每个 k 下的 SSE
for k in ks:
    kmeans = KMeans(n_clusters=k)
    kmeans.fit(X)
    SSE.append(sum(np.min(cdist(X, kmeans.cluster_centers_, 'euclidean'), axis=1)) / X.shape[0])

# 绘制 SSE - k 图像
plt.plot(ks, SSE, 'bx-', markersize=8, linewidth=2)
plt.xlabel('k')
plt.ylabel('SSE')
plt.title('Elbow Method For Optimal k')
plt.show()

首先,我们生成随机的测试数据(这里为二维数据),并指定最大的聚类数量。然后,在 k 的遍历范围内,对每个 k 值分别运行 KMeans 算法,并计算对应的 SSE 值。最后,将每个 k 值对应的 SSE 通过 matplotlib 绘制成 SSE - k 图像。

运行该程序,可以得到如下图像:

SSE - k 图像

最后,我们可以通过图像肘部所在的位置确定最优的聚类数量。在本例中,可以看到肘部处于 k=3 时,因此最终的聚类数量为 3。

总结

KMeans 是一种常用的聚类算法,在实际问题中,聚类数量的选择是一个较为困难的问题。肘部方法是一种通用的解决方案,其基本思想是通过 SSE - k 图像确定最优的聚类数量。在 Python 中,我们可以很方便地使用 sklearn 和 matplotlib 库实现该方法。