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

How to find most optimal number of clusters with K-Means clustering in Python

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

我想根据相似用户的评论对相似用户进行聚类,认为将相似电影评为好电影的用户也可能将一部未被同一集群中任何用户评价的电影评为好电影。我将余弦相似性度量与 k 均值聚类一起使用。 csv文件如下所示:

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

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

我会很感激一些帮助..

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

你可以用弯头法。

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

从可视化数据开始是很常见的。有时在图形上很明显,有 N classes/clusters。其他时候,您可能会看到它是 <5、<10 还是 <100 类。这真的取决于你的数据。

另一种常见的方法是使用 Bayesian Information Criterium (BIC) or the Akaike Information Criterium (AIC).

主要的收获是很多分类问题都可以产生最佳结果,例如你有多少输入就有多少类:每个输入都完全适合它自己的集群。

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

来自维基百科:

When fitting models, it is possible to increase the likelihood by adding parameters, but doing so may result in overfitting. Both BIC and AIC attempt to resolve this problem by introducing a penalty term for the number of parameters in the model; the penalty term is larger in BIC than in AIC.

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

尽管如此,还是有一些量化的措施。他们中的大多数基于“与不同集群中的点相比,某个集群中的点彼此之间的相似度有多少?”的概念。我建议您查看 clustering evaluation 上的 scikit-learn 文档。查看所有不需要 labels_true 的技术(即所有无监督技术)。 一旦您对某个聚类的“优度”有了定量测量,您通常会观察这个量是如何随着聚类数量的变化而变化的;这种方法称为 Elbow Method.

这里有一些代码使用 K-Means 算法,所有可能的 K 值从 2 到 30,计算每个 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().