【问题标题】:Is non-identical not enough to be considered 'distinct' for kmeans centroids?对于 kmeans 质心,不相同是否不足以被认为是“不同的”?
【发布时间】:2020-08-16 10:47:50
【问题描述】:

我对提供质心的 kmeans 聚类有疑问。我看到已经问过同样的问题( K-means: Initial centers are not distinct),但该帖子中的解决方案不适用于我的情况。

我使用ClusterR::Kmeans_arma 选择了质心。我使用mgcv::uniquecombs 确认我的质心不相同,但仍然出现initial centers are not distinct 错误。

> dim(t(dat))
[1] 13540 11553
> centroids = ClusterR::KMeans_arma(data = t(dat), centers = 561, 
                                    n_iter = 50, seed_mode = "random_subset",
                                    verbose = FALSE, CENTROIDS = NULL)
> dim(centroids)
[1]   561 11553
> x = mgcv::uniquecombs(centroids)
> dim(x)
[1]   561 11553
> res = kmeans(t(dat), centers = centroids, iter.max = 200)
Error in kmeans(t(dat), centers = centroids, iter.max = 200) : 
  initial centers are not distinct

有解决此问题的建议吗?谢谢!

【问题讨论】:

    标签: k-means armadillo centroid


    【解决方案1】:

    我用以下数据复制了你提到的问题:

        cols = 13540
        rows = 11553
    
        set.seed(1)
        vec_dat = runif(rows * cols)
    
        dat = matrix(vec_dat, nrow = rows, ncol = cols)
        dim(dat)
    
        dat = t(dat)
        dim(dat)
    

    “ClusterR::KMeans_arma()”函数中没有“centers”参数,因此我假设您实际上是指“clusters”,

    centroids = ClusterR::KMeans_arma(data = dat, 
                                      clusters = 561,                
                                      n_iter = 50,
                                      seed_mode = "random_subset",
                                      verbose = TRUE, 
                                      CENTROIDS = NULL)
    
    str(centroids)
    dim(centroids)
    

    “质心”是“k 均值聚类”类的矩阵。如果您的意图是来集群,那么您可以使用,

    clust = ClusterR::predict_KMeans(data = dat, 
                                     CENTROIDS = centroids, 
                                     threads = 6)
    length(unique(clust))    # 561
    
    class(centroids)   # "k-means clustering"
    

    如果你想将'centroids' 传递给基本 R 'kmeans' 函数,你必须将 'centroids' 对象的 'class' 设置为 NULL,因为基本 R 'kmeans' 函数在内部使用基本R 'duplicated()' 函数(您可以通过在 R 控制台中使用 print(kmeans) 来查看它)它不能将 'centroids' 对象识别为矩阵或 data.frame(它是类“k-means”的对象clustering") 并按列而不是按行执行检查。因此,以下内容应该适用于您的情况,

    class(centroids) = NULL
    
    dups = duplicated(centroids)
    sum(dups)                        # this should actually give 0
    
    res = kmeans(dat, centers = centroids, iter.max = 200)
    

    我对“ClusterR::predict_KMeans()”做了一些调整,特别是我添加了“threads”参数并检查重复项,因此如果您想使用多核集群必须使用从 Github 安装包,

    remotes::install_github('mlampros/ClusterR', 
                            upgrade = 'always', 
                            dependencies = TRUE, 
                            repos = 'https://cloud.r-project.org/')
    

    更改将在 CRAN 包的下一版本“1.2.2”中生效


    更新关于输出和性能(基于您的评论):

    data(dietary_survey_IBS, package = 'ClusterR')
    
    kmeans_arma = function(data) {
    
      km_cl = ClusterR::KMeans_arma(data, 
                                    clusters = 2, 
                                    n_iter = 10, 
                                    seed_mode = "random_subset",
                                    seed = 1)
    
      pred_cl = ClusterR::predict_KMeans(data = data,
                                         CENTROIDS = km_cl,
                                         threads = 1)
    
      return(pred_cl)
    }
    
    km_arma = kmeans_arma(data = dietary_survey_IBS)
    
    
    
    km_algos = c("Hartigan-Wong", "Lloyd", "Forgy", "MacQueen")
    
    for (algo in km_algos) {
    
      cat('base-kmeans-algo:', algo, '\n')
    
      km_base = kmeans(dietary_survey_IBS, 
                       centers = 2,
                       iter.max = 10,
                       nstart = 1,                     # can be set to 5 or 10 etc.
                       algorithm = algo)
    
      km_cl = as.vector(km_base$cluster)
    
      print(table(km_arma, km_cl))
      cat('--------------------------\n')
    }
    
    
    microbenchmark::microbenchmark(kmeans(dietary_survey_IBS, 
                                          centers = 2,
                                          iter.max = 10,
                                          nstart = 1,                     # can be set to 5 or 10 etc.
                                          algorithm = algo), kmeans_arma(data = dietary_survey_IBS), times = 100)
    

    对于所有可用的“base R kmeans”算法(您也可以针对自己的数据集进行测试),“base R kmeans”和“kmeans_arma”函数之间的输出集群没有任何显着差异。我不确定“犰狳”库在内部使用哪种算法,而且“base R kmeans”包括“nstart”参数(您可以查阅文档以获取更多信息)。关于性能,对于中小型数据集,您不会看到任何实质性差异,但由于犰狳库在内部使用 OpenMP 以防您的计算机有超过 1 个内核,然后对于大数据集,我认为'ClusterR:: KMeans_arma' 函数将更快地返回“质心”。

    【讨论】:

    • 一个简单的问题,你知道直接比较stats::kmeansClusterR::predict_KMeans之间的输出/性能的任何参考吗?
    • @Sehyun 哦,我根据你的评论更新了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 2013-11-02
    相关资源
    最近更新 更多