如何在 Python 中使用 K-Means 聚类找到最佳的聚类数量

Posted

技术标签:

【中文标题】如何在 Python 中使用 K-Means 聚类找到最佳的聚类数量【英文标题】:How to find most optimal number of clusters with K-Means clustering in Python 【发布时间】:2021-10-11 15:15:03 【问题描述】:

我是聚类算法的新手。我有一个包含 200 多部电影和 100 多个用户的电影数据集。所有用户都对至少一部电影进行了评分。值 1 表示好,0 表示差,如果注释者别无选择,则为空白。

我想根据他们的评论对相似的用户进行聚类,这样的想法是,将类似电影评价为好的用户也可能将同一聚类中没有任何用户评价的电影评价为好。我使用了 k-means 聚类的余弦相似度度量。 csv文件如下图:

  UserID         M1     M2       M3  ...............  M200                          
  user1          1      0                               0     
  user2          0      1        1                                      
  user3          1      1                               1                                                                         
    .
    .
    .
    .
 user100         1      0        1                                       

我面临的问题是我不知道如何为该数据集找到最佳数量的集群,然后绘制这些集群的图表。我用 k-means 对它们进行聚类,这没有问题,但我想知道这个数据集最稳定或最佳的聚类数量。

我会很感激一些帮助..

【问题讨论】:

通常你使用贝叶斯信息标准来做到这一点 @user3684792,你能举个例子吗? 【参考方案1】:

从可视化数据开始是很常见的。有时在图形上很明显,有 N 个类/集群。其他时候,您可能会看到它是

另一种常见的方法是使用Bayesian Information Criterium (BIC) 或Akaike Information Criterium (AIC)。

主要的收获是,如果很多分类问题可以产生最佳结果,例如您拥有与输入一样多的类:每个输入都非常适合自己的集群。

BIC/AIC 惩罚高维解决方案,因为更简单的模型通常更好/更稳定。 IE。它们泛化得更好,过拟合更少。

来自***:

在拟合模型时,可以通过添加参数来增加似然度,但这样做可能会导致过拟合。 BIC 和 AIC 都试图通过对模型中的参数数量引入惩罚项来解决这个问题; BIC中的惩罚项比AIC中的要大。

【讨论】:

非常感谢@Morten 提供详细信息。我会研究你提到的方法。虽然我是聚类的新手,但我需要一些实际示例来更好地解释我将尝试搜索。【参考方案2】:

聚类是无监督机器学习方法的一部分。与监督方法相反,在无监督方法中,没有一种直接的方法可以确定在特定数据集上训练的一组模型中的“最佳”模型。

尽管如此,还是有一些量化的措施。它们大多是基于“某个簇中的点与不同簇中的点相比,它们之间的相似度高多少?”的概念。我建议您查看clustering evaluation 上的 scikit-learn 文档。看看所有不需要labels_true 的技术(即所有无监督技术)。 一旦你对某个聚类的“好坏”有了一个量化的衡量标准,你通常会观察这个数量在改变聚类数量的同时是如何演变的;这种方法称为Elbow Method。

这里是一些代码,它使用了从 2 到 30 的所有可能的 K 值的 K-Means 算法,计算每个 K 值的各种分数,并将所有分数存储在 DataFrame 中。

seed_random = 1

fitted_kmeans = 
labels_kmeans = 
df_scores = []
k_values_to_try = np.arange(2, 31)
for n_clusters in k_values_to_try:
    
    #Perform clustering.
    kmeans = KMeans(n_clusters=n_clusters,
                    random_state=seed_random,
                    )
    labels_clusters = kmeans.fit_predict(X)
    
    #Insert fitted model and calculated cluster labels in dictionaries,
    #for further reference.
    fitted_kmeans[n_clusters] = kmeans
    labels_kmeans[n_clusters] = labels_clusters
    
    #Calculate various scores, and save them for further reference.
    silhouette = silhouette_score(X, labels_clusters)
    ch = calinski_harabasz_score(X, labels_clusters)
    db = davies_bouldin_score(X, labels_clusters)
    tmp_scores = "n_clusters": n_clusters,
                  "silhouette_score": silhouette,
                  "calinski_harabasz_score": ch,
                  "davies_bouldin_score": db,
                  
    df_scores.append(tmp_scores)

#Create a DataFrame of clustering scores, using `n_clusters` as index, for easier plotting.
df_scores = pd.DataFrame(df_scores)
df_scores.set_index("n_clusters", inplace=True)

此代码假定您的所有数字特征都在 DataFrame X 中。 所有聚类性能指标都存储在df_scores DataFrame 中。 您可以通过绘制来自df_scores 的列来轻松使用肘法;比如想看Silhouette Score的肘部图,可以使用df_scores["silhouette_score"].plot()

【讨论】:

非常感谢@Enrico_Gandini。我将使用上面在问题中提供的示例进行检查。由于我基于相似的评分对用户进行聚类,所以我假设数字特征是给电影的评分值为 0 和 1,没有评分则为 null。 是@ToBeEXP,在您的场景中,数值特征是包含0和1的列。通常,聚类算法需要数据完整,因此您不能有空值。您可以决定用 -1 填充您的空值,并记住 -1 对应于“某个用户没有为这部电影给出的答案”。一般来说,我的回答是关于如何评估聚类算法并找到最佳数量的聚类。考虑到您的特定数据集,我什至不确定 KMeans 是个好主意!也许还有更具体的算法。 谢谢恩里科。为什么你认为在我的情况下 K-means 不是一个好主意?如果您有时间就您的最后一点做出承诺。 @ToBeEXP,我认为 K-means 和其他聚类算法旨在用于连续数值特征。 K-means 特别是通过计算点之间的欧几里得距离来定义集群,我认为欧几里得距离对你的数据没有意义。如果你改变距离度量(你提到你想使用余弦距离),我不确定 K-means 的基本假设是否仍然成立。在我看来,您应该尝试研究其他类型的算法,例如关联规则或顺序模式,但我不是这些方面的专家! 谢谢恩里科。好吧,我仍然是初学者,这不完全是我的研究领域,但我必须这样做。您提供的信息非常有帮助,我将研究其他可能性。实际上正如你提到的不能有空值,实际上我已经替换了空值。【参考方案3】:

你可以使用肘法。

K-Means 的基本含义是对数据点进行聚类,以使“聚类内平方和 (a.k.a WSS)”的总和最小化。因此,您可以将 k 从 2 更改为 n,同时还可以计算每个点的 WSS;绘制图形和曲线。找到弯曲的位置,这可以被认为是最佳的集群数量!

【讨论】:

你能举个例子吗?【参考方案4】:

您可以使用基尼指数作为指标,然后根据该指标进行网格搜索。如果您还有其他问题,请告诉我。

【讨论】:

我在我的问题中提到我是集群的新手,我不知道你刚才提到了什么。您能否举一个例子,可能是我上面提到的数据集示例?谢谢

以上是关于如何在 Python 中使用 K-Means 聚类找到最佳的聚类数量的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 k-means (Flann with python) 对文档进行聚类?

如何在k-means python中输入或确定聚类中心?

在 Python 中计算位置数据的 K-means 聚类

k-means+python︱scikit-learn中的KMeans聚类实现( + MiniBatchKMeans)

用 PCA 解释 K-Means 聚类 - Python

在python中使用k-means聚类提取质心?