在 K-Means 聚类中确定 K

数据挖掘 Python 聚类 k-均值
2021-10-11 15:00:10

我有几个用户的工资数据(Python 列表)。

现在我正在使用 KMeans 对它们进行聚类。

鉴于这些数据,有没有办法通过程序自动找出“K”的最佳值?

我试过剪影分析

k最高silhouette_avg分。这是最好的方法吗?

4个回答

王凯军、王百杰、彭柳青。“CVAP:聚类分析验证。” 数据科学杂志 0 (2009): 0904220071.:

为了衡量聚类结果的质量,有两种有效性指标:外部指标和内部指标。

外部索引是衡量两个分区之间一致性的指标,其中第一个分区是先验已知的聚类结构,第二个分区是聚类过程的结果(Dudoit 等,2002)。

内部指标用于衡量没有外部信息的聚类结构的好坏(Tseng 等,2005)。

对于外部索引,我们基于数据集(或集群标签)的已知集群结构评估集群算法的结果。

对于内部指标,我们使用数据集中固有的数量和特征来评估结果。最佳聚类数通常根据内部有效性指标确定。

(Dudoit 等人,2002 年):Dudoit, S. & Fridlyand, J. (2002) 一种基于预测的重采样方法,用于估计数据集中的集群数量。基因组生物学,3(7):0036.1-21。

(Tseng et al., 2005):Thalamuthu, A, Mukhopadhyay, I, Zheng, X, & Tseng, GC (2006) 微阵列分析中基因聚类方法的评估和比较。生物信息学,22(19):2405-12。


在您的情况下,您需要一些内部索引,因为您没有先验聚类结构。存在数十个内部索引,例如:

  • 剪影索引(在MATLAB中实现)
  • 戴维斯-博尔丁
  • 卡林斯基-哈拉巴斯
  • 邓恩指数(在MATLAB中实现)
  • R平方指数
  • 休伯特-莱文 (C-index)
  • Krzanowski-Lai 指数
  • 哈蒂根指数
  • 均方根标准差 (RMSSTD) 指数
  • 半偏 R 平方 (SPR) 指数
  • 两个簇之间的距离 (CD) 索引
  • 加权内部指数
  • 同质指数
  • 分离指数

它们每个都有优点和缺点,但至少它们会给你一个更正式的比较基础。MATLAB 工具箱CVAP可能很方便,因为它包含许多内部有效性指标。


更多信息:

根据你的问题,你没有集群的先验知识,你想估计它。K-means 对异常值不敏感,因此如果使用任何索引评分,那么它会在那个时候失败。如果您在索引评分之前知道集群,则可以衡量集群质量。在这里,根据您的问题,您需要凝聚聚类,我认为它可以提供与 K-means 相比的值。作为分层算法,它不需要给出k,但需要指定叶子节点的数量。默认情况下它是“2”,它适用于大多数情况。你只需要关心从哪里切割你可能通过查看树状图得到的边缘。

在这种情况下,找出更好的“K”值的最佳方法是

  1. 领域知识,您可以在其中确定要划分的组数。
  2. 在 K 均值聚类中,您可以在“X 轴”- K 值、“Y 值”- 误差值上绘制图形。通过这种方式,您可以在图上找到最佳 k 值作为肘点。

除了剪影得分,您还可以使用众所周知的肘部规则

我建议您也使用不需要预先指定集群数量的算法,例如 DBSCAN 或 MeanShift,以便您可以比较为这些算法找到的集群数量与您指定为 K 均值的集群数量。

最后,请注意 k 均值可能会受到数据缩放的影响,因此您需要先缩放数据以找到特征之间的适当距离。此外,K 均值对质心初始化很敏感,因此您可以多次运行算法并检查每次聚类的差异。

**编辑:如果您想使用肘部规则以编程方式找到最佳集群数,您应该查看ElbowRuleRepo

例子:

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from kneed import KneeLocator

plt.scatter(X[:,0], X[:,1])

lista = list()
for k in range(1,7):
    kmeans = KMeans(n_clusters= k).fit(X)
    inertia = kmeans.inertia_
    lista.append(inertia)

x = range(1,7)
y = lista
plt.plot(x,y)

# From the plots we see that the optimal number of clusters is 3
optimal = KneeLocator(x = x, y = y, curve="convex", 
direction="decreasing")
print(f"The optimal number of clusters is {optimal.knee} with an inertia of {optimal.knee_y}")