繁体   English   中英

打破k-means集群之间的联系

[英]break tie between k-means cluster

我有应用k-means的数据集,并且有两个聚类,但是从特定点(x,y)到两个聚类的距离是相同的,然后该点将在哪个聚类中。 请帮我。 提前致谢。

tldr;

在tie的情况下,k-means聚类将随机地将模糊点分配给聚类。 (这是基于R的k均值聚类kmeans的实现。)


基于R中的iris数据的具体示例

  1. 让我们从加载必要的R库开始

     library(broom) library(tidyverse) 
  2. 对于此示例,我们将使用iris数据集中的Petal.LengthPetal.Width测量值,为简单起见,不包括“virginica”测量值,以便“setosa”和“versicolor”测量形成我们的两组。

     df <- iris %>% filter(Species != "virginica") %>% select(starts_with("Petal"), Species) 
  3. 我们现在使用k均值聚类,k = 2,并为每个( Petal.LengthPetal.Width )测量指定一个聚类标签; 由于分配哪个组是“1”而哪个组是“2”是随机的,我们使用固定种子进行再现。

     set.seed(2018) kcl <- kmeans(df %>% select(-Species), 2) df <- augment(kcl, df) 
  4. 我们展示了Petal.LengthPetal.Width的散点图; 已知的Species标签由不同的颜色显示,推断的群集关联由不同的符号显示。

     ggplot(df, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point(aes(shape = .cluster), size = 3) 

    在此输入图像描述

  5. 让我们手动计算平方成对距离的簇内总和; 因为我们稍后也需要这个,所以我们将创建一个函数calculate_d

     calculate_d <- function(df) { df %>% select(.cluster, Petal.Length, Petal.Width) %>% group_by(.cluster) %>% nest() %>% mutate(dist = map_dbl(data, ~sum(as.matrix(dist(.x)^2)) / (2 * nrow(.x)))) %>% pull(dist) } calculate_d(df) #[1] 2.0220 12.7362 

    注意距离是如何与簇内平方和(WCSS)相同的

     kcl$withinss #[1] 2.0220 12.7362 
  6. 现在让我们添加一个与两个聚类中心具有相同欧氏距离的新测量:为此,如果用直线连接它们,我们选择恰好位于两个聚类中心之间的点。 我们所需要的只是构建这一点的一些基本三角函数:

     z <- kcl$centers[2, ] - kcl$center[1, ] theta <- atan(z[2] / z[1]) dy <- sin(theta) * dist(kcl$centers) / 2 dx <- cos(theta) * dist(kcl$centers) / 2 x <- as.numeric(kcl$centers[1, 1] + dx) y <- as.numeric(kcl$centers[1, 2] + dy) 

    我们将新点与2个集群中心一起存储在新的data.frame 前两行给出了簇“1”和“2”的位置,第三行包含我们的新点。

     df2 <- bind_rows(as.data.frame(kcl$centers), c(Petal.Length = x, Petal.Width = y)) 

    让我们在我们的( Petal.LengthPetal.Width )测量结果上显示新点以及聚类中心。

     df2 <- bind_rows(as.data.frame(kcl$centers), c(Petal.Length = x, Petal.Width = y)) ggplot(df, aes(Petal.Length, Petal.Width)) + geom_point(aes(colour = Species, shape = .cluster), size = 3) + geom_point(data = df2, aes(Petal.Length, Petal.Width), size = 4) 

    在此输入图像描述

    我们确认新点与每个聚类中心之间的欧氏距离平方确实相同; 为此,我们计算新点“3”与聚类中心“1”和“2”的成对距离:

     as.matrix(dist(df2))[, 3] # 1 2 3 #1.4996 1.4996 0.0000 
  7. 现在让我们将新点添加到( Petal.LengthPetal.Width )测量中,并计算成对距离的平方和,首先将新点指定给簇“1”,然后将新点指定给簇“2”。

     # Add new point and assign to cluster "1" df.1 <- df %>% bind_rows(cbind.data.frame( Petal.Length = x, Petal.Width = y, Species = factor("setosa", levels = levels(df$Species)), .cluster = factor(1, levels = 1:2))) calculate_d(df.1) #[1] 4.226707 12.736200 # Add new point and assign to cluster "2" df.2 <- df %>% bind_rows(cbind.data.frame( Petal.Length = x, Petal.Width = y, Species = factor("versicolor", levels = levels(df$Species)), .cluster = factor(2, levels = 1:2))) calculate_d(df.2) #[1] 2.02200 14.94091 

    请注意,即使新点距离任一群集中心的距离完全相同,群内平方成对距离也会有所不同。 但是请注意,群内平方成对距离的总和是如何相同的!

     sum(calculate_d(df.1)) #[1] 16.96291 sum(calculate_d(df.2)) #[1] 16.96291 identical(sum(calculate_d(df.2)), sum(calculate_d(df.1))) # [1] TRUE 
  8. 为了表明kmeans随机地将新点分配给任一群集,我们重复地对数据进行聚类。 为此,我们定义了一个便利函数,它返回k-means聚类后新点的相应Species

     kmeans_cluster_data <- function(df) { kcl <- kmeans(df %>% select(-Species), 2) df <- augment(kcl, df) map_cluster_to_Species <- df[1:(nrow(df) - 1), ] %>% count(Species, .cluster) %>% split(., .$.cluster) map_cluster_to_Species[[ df[nrow(df), ] %>% pull(.cluster) %>% as.character()]]$Species %>% as.character() } 

    我们现在反复聚集相同的数据100次。

     bind_cols( Iteration = 1:100, Species = map_chr(1:100, ~kmeans_cluster_data(df.1 %>% select(-.cluster)))) %>% ggplot(aes(Iteration, Species, group = 1)) + geom_line() + labs(title = "Assignment of new point to group") 

    在此输入图像描述

    注意新点如何随机分配给任何一个Species组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM