【问题标题】:Weighted Kmeans R加权 Kmeans R
【发布时间】:2018-07-31 18:06:56
【问题描述】:

我想对具有三个变量(列)的数据集(即 Sample_Data)进行 Kmeans 聚类,如下所示:

     A  B  C
1    12 10 1
2    8  11 2
3    14 10 1
.    .   .  .
.    .   .  .
.    .   .  .

以一种典型的方式,在对列进行缩放并确定簇的数量之后,我将在 R 中使用这个函数:

Sample_Data <- scale(Sample_Data)
output_kmeans <- kmeans(Sample_Data, centers = 5, nstart = 50)

但是,如果对变量有偏好怎么办?我的意思是,假设变量(列)A 比其他两个变量更重要? 如何在模型中插入它们的权重? 谢谢大家

【问题讨论】:

    标签: r machine-learning cluster-analysis k-means


    【解决方案1】:

    我遇到了同样的问题,这里的答案对我来说并不令人满意。

    我们都想要的是 R 中的观察加权 k 均值聚类。我们问题的一个很好的可读示例是这个链接:https://towardsdatascience.com/clustering-the-us-population-observation-weighted-k-means-f4d58b370002

    然而,使用 flexclust 包的解决方案并不能简单地满足 b/c,所使用的算法不是“标准”k-means 算法,而是“硬竞争学习”算法。区别在上面和包装描述中都有很好的描述。

    我浏览了许多站点,并没有在 R 中找到任何解决方案/包,以便用于执行带有加权观察的“标准”k-means 算法。我还想知道为什么 flexclust 包明确不支持使用标准 k-means 算法的权重。如果有人对此有解释,请随时分享!

    所以基本上你有两个选择:首先,重写 flexclust-algorithm 以在标准方法中启用权重。或者,您可以将加权聚类质心估计为起始质心,并仅通过一次迭代执行标准 k-means 算法,然后计算新的加权聚类质心并通过一次迭代执行 k-means,依此类推,直到达到收敛。

    我使用了第二种选择 b/c,这对我来说是更简单的方法。我用的是data.table包,希望大家熟悉一下。

    rm(list=ls())
    
    library(data.table)
    
    ### gen dataset with sample-weights
    dataset     <- data.table(iris)
    dataset[, weights:= rep(c(1, 0.7, 0.3, 4, 5),30)] 
    dataset[, Species := NULL]
    
    
    ### initial hclust for estimating weighted centroids
    clustering    <- hclust(dist(dataset[, c(1:4)], method = 'euclidean'), 
                            method = 'ward.D2')
    no_of_clusters <- 4
    
    
    ### estimating starting centroids (weighted)
    weighted_centroids  <- matrix(NA, nrow = no_of_clusters, 
                                  ncol =  ncol(dataset[, c(1:4)]))
    for (i in (1:no_of_clusters))
    {
     weighted_centroids[i,] <- sapply(dataset[, c(1:4)][cutree(clustering, k = 
                                                        no_of_clusters) == i,], weighted.mean, w = dataset[cutree(clustering, k = no_of_clusters) == i, weights])
     }
    
    
    ### performing weighted k-means as explained in my post
    iter            <- 0 
    cluster_i       <- 0
    cluster_iminus1 <- 1
    
    ## while loop: if number of iteration is smaller than 50 and cluster_i (result of 
    ## current iteration) is not identical to cluster_iminus1 (result of former 
    ## iteration) then continue
    while(identical(cluster_i, cluster_iminus1) == F && iter < 50){
    
      # update iteration  
      iter <- iter + 1
    
      # k-means with weighted centroids and one iteration (may generate warning messages 
      # as no convergence is reached)
      cluster_kmeans <- kmeans(x = dataset[, c(1:4)], centers = weighted_centroids, iter = 1)$cluster
    
      # estimating new weighted centroids
      weighted_centroids <- matrix(NA, nrow = no_of_clusters, 
                                   ncol=ncol(dataset[,c(1:4)]))
      for (i in (1:no_of_clusters))
    {
     weighted_centroids[i,] <- sapply(dataset[, c(1:4)][cutree(clustering, k = 
                                                        no_of_clusters) == i,], weighted.mean, w = dataset[cutree(clustering, k = no_of_clusters) == i, weights])
     }
    
      # update cluster_i and cluster_iminus1
      if(iter == 1) {cluster_iminus1 <- 0} else{cluster_iminus1 <- cluster_i}
      cluster_i <- cluster_kmeans
    
    }
    
    
    ## merge final clusters to data table
    dataset[, cluster := cluster_i]
    

    【讨论】:

      【解决方案2】:

      如果要增加变量(列)的权重,只需将其乘以常数 c > 1。

      证明这增加了 SSQ 优化目标中的权重是微不足道的。

      【讨论】:

      • 谢谢。这应该在什么阶段完成?规模之后还是规模之前?你能说出一个参考吗?
      • 缩放 = 加权。所以不要盲目地应用你在一些例子中找到的一些随机缩放函数。而是选择适当的权重。对此没有参考,从目标函数中可以明显看出您需要为每个属性选择适当的比例。
      • 说我们有三个变量:货币价值(范围在 1000 到 10^6 之间)频率(范围在 1 到 10 之间)延迟(范围在 1 到 250 之间)你认为我不应该缩放它们吗?或者找到合适的尺度的方法是什么?
      • 如果你想给它们加权,缩放是多余的。只需为否则会主导结果的变量选择较小的权重。但要以聪明的方式做到这一点。首先将它们缩放到 [0;1] 没有任何好处,那就是做两次。请注意,通常,当您拥有如此不同比例的轴时,结果将毫无用处。 SSQ 目标通常缺乏任何真正的相关性,然后您的聚类优化了一个无用的数量。
      • 我相信我还要多学习。顺便谢谢你的帮助
      【解决方案3】:

      您必须使用 kmeans 加权聚类,就像在 flexclust 包中介绍的那样:

      https://cran.r-project.org/web/packages/flexclust/flexclust.pdf

      功能

      cclust(x, k, dist = "euclidean", method = "kmeans",
      weights=NULL, control=NULL, group=NULL, simple=FALSE,
      save.data=FALSE)
      

      对数据矩阵执行 k 均值聚类、硬竞争学习或神经气体。 weights 在拟合过程中使用的可选权重向量。仅与艰苦的竞争学习结合使用。

      一个使用虹膜数据的玩具示例:

      library(flexclust)
      data(iris)
      cl <- cclust(iris[,-5], k=3, save.data=TRUE,weights =c(1,0.5,1,0.1),method="hardcl")
      cl  
          kcca object of family ‘kmeans’ 
      
          call:
          cclust(x = iris[, -5], k = 3, method = "hardcl", weights = c(1, 0.5, 1, 0.1), save.data = TRUE)
      
          cluster sizes:
      
           1  2  3 
          50 59 41 
      

      从 clust 的输出中可以看出,同样使用竞争性学习的家庭始终是 kmenas。 差异与训练阶段的集群分配有关:

      如果方法是“kmeans”,经典的kmeans算法由 使用 MacQueen (1967),它通过重复移动所有集群来工作 中心到它们各自的 Voronoi 集的平均值。如果 "hardcl", 使用在线更新(AKA 硬竞争学习),这很有效 通过从 x 中随机抽取一个观测值并移动最近的 中心朝向那个点(例如,Ripley 1996)。

      weights 参数只是一个数字序列,一般我使用介于 0.01(最小权重)和 1(最大权重)之间的数字。

      【讨论】:

      • 谢谢,但它提到,权重仅适用于硬竞争学习。它和Kmeans一样吗?你碰巧知道在模型中插入权重的手动格式吗?例如,在加权平均值中,我们可以使用 R 中的命令,或者我们可以手动进行数学运算。你知道将权重插入 kmeans 模型背后的逻辑吗?
      • 感谢您的好意和解释。作为最后一个问题(希望如此),对权重是否有任何限制?例如 sum (weights)=1 或任何东西?你能介绍一下我的参考资料,以便更多地研究为变量分配权重吗?
      • 这个函数对权重没有限制。你可以在这里找到一个应用程序:towardsdatascience.com/…
      猜你喜欢
      • 2015-12-03
      • 2013-04-29
      • 2013-02-23
      • 2018-04-17
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 2013-04-08
      • 2012-09-16
      相关资源
      最近更新 更多