使用 dplyr 和 broom 在训练和测试集上计算 kmeans
Posted
技术标签:
【中文标题】使用 dplyr 和 broom 在训练和测试集上计算 kmeans【英文标题】:Using dplyr and broom to compute kmeans on a training and test set 【发布时间】:2017-02-27 05:15:11 【问题描述】:我正在使用 dplyr 和 broom 为我的数据计算 kmeans。我的数据包含 X 和 Y 坐标的测试和训练集,并按某个参数值(在本例中为 lambda)分组:
mds.test = data.frame()
for(l in seq(0.1, 0.9, by=0.2))
new.dist <- run.distance.model(x, y, lambda=l)
mds <- preform.mds(new.dist, ndim=2)
mds.test <- rbind(mds.test, cbind(mds$space, design[,c(1,3,4,5)], lambda=rep(l, nrow(mds$space)), data="test"))
> head(mds.test)
Comp1 Comp2 Transcripts Genes Timepoint Run lambda data
7A_0_AAGCCTAGCGAC -0.06690476 -0.25519106 68125 9324 Day 0 7A 0.1 test
7A_0_AAATGACTGGCC -0.15292848 0.04310200 28443 6746 Day 0 7A 0.1 test
7A_0_CATCTCGTTCTA -0.12529445 0.13022908 27360 6318 Day 0 7A 0.1 test
7A_0_ACCGGCACATTC -0.33015913 0.14647857 23038 5709 Day 0 7A 0.1 test
7A_0_TATGTCGGAATG -0.25826098 0.05424976 22414 5878 Day 0 7A 0.1 test
7A_0_GAAAAAGGTGAT -0.24349387 0.08071162 21907 6766 Day 0 7A 0.1 test
我有head
上面的测试数据集,但我也有一个名为mds.train
的数据集,其中包含我的训练数据坐标。我的最终目标是对按 lambda 分组的两个集合运行 k-means,然后计算训练中心测试数据的 within.ss、between.ss 和 total.ss。感谢扫帚上的a great resource,我只需执行以下操作即可为测试集的每个 lambda 运行 kmeans:
test.kclusts = mds.test %>%
group_by(lambda) %>%
do(kclust=kmeans(cbind(.$Comp1, .$Comp2), centers=length(unique(design$Timepoint))))
然后我可以为每个 lambda 中的每个集群计算这些数据的中心:
test.clusters = test.kclusts %>%
group_by(lambda) %>%
do(tidy(.$kclust[[1]]))
这就是我卡住的地方。我如何计算与reference page(例如kclusts %>% group_by(k) %>% do(augment(.$kclust[[1]], points.matrix))
)上类似显示的特征分配,其中我的points.matrix
是mds.test
,它是一个data.frame,其中length(unique(mds.test$lambda))
的行数是应有的行数?有没有办法以某种方式使用训练集中的中心来根据测试分配计算 glance()
统计数据?
任何帮助将不胜感激!谢谢!
编辑:更新进度。我已经弄清楚如何汇总测试/培训作业,但在尝试从两组计算 kmeans 统计数据时仍然遇到问题(测试中心的培训作业和培训中心的测试作业)。更新代码如下:
test.kclusts = mds.test %>% group_by(lambda) %>% do(kclust=kmeans(cbind(.$Comp1, .$Comp2), centers=length(unique(design$Timepoint))))
test.clusters = test.kclusts %>% group_by(lambda) %>% do(tidy(.$kclust[[1]]))
test.clusterings = test.kclusts %>% group_by(lambda) %>% do(glance(.$kclust[[1]]))
test.assignments = left_join(test.kclusts, mds.test) %>% group_by(lambda) %>% do(augment(.$kclust[[1]], cbind(.$Comp1, .$Comp2)))
train.kclusts = mds.train %>% group_by(lambda) %>% do(kclust=kmeans(cbind(.$Comp1, .$Comp2), centers=length(unique(design$Timepoint))))
train.clusters = train.kclusts %>% group_by(lambda) %>% do(tidy(.$kclust[[1]]))
train.clusterings = train.kclusts %>% group_by(lambda) %>% do(glance(.$kclust[[1]]))
train.assignments = left_join(train.kclusts, mds.train) %>% group_by(lambda) %>% do(augment(.$kclust[[1]], cbind(.$Comp1, .$Comp2)))
test.assignments$data = "test"
train.assignments$data = "train"
merge.assignments = rbind(test.assignments, train.assignments)
merge.assignments %>% filter(., data=='test') %>% group_by(lambda) ... ?
我在下面附上了一个图表,说明了我在这一点上的进展。重申一下,我想为训练数据中心的测试分配/坐标(中心看起来的图)计算 kmeans 统计量(在平方和内、总平方和之间以及在平方和之间):
【问题讨论】:
看起来有一些关于制作 tidymodels 配方或模型规范的讨论,例如recipes::step_kmeans() (请参阅此处的对话和此处的链接:github.com/tidymodels/embed/issues/77#issuecomment-801300749。但尚未完成。还有 widyr::widely_kmeans() 但这也不容易应用于测试集. 【参考方案1】:一种方法是……
-
通过broom提取指定集群质心的表(基于训练集构建)。
计算测试集中每个点与使用训练集构建的每个聚类质心的距离。可以通过fuzzyjoin 包做到这一点。
测试点与欧几里得距离最短的聚类质心代表其分配的聚类。
您可以从那里计算任何感兴趣的指标。
使用从 tidymodels 的集群 example 中提取的更简单数据集,请参见下文。
library(tidyverse)
library(rsample)
library(broom)
library(fuzzyjoin)
# data and train / test set-up
set.seed(27)
centers <- tibble(
cluster = factor(1:3),
num_points = c(100, 150, 50), # number points in each cluster
x1 = c(5, 0, -3), # x1 coordinate of cluster center
x2 = c(-1, 1, -2) # x2 coordinate of cluster center
)
labelled_points <-
centers %>%
mutate(
x1 = map2(num_points, x1, rnorm),
x2 = map2(num_points, x2, rnorm)
) %>%
select(-num_points) %>%
unnest(cols = c(x1, x2))
points <-
labelled_points %>%
select(-cluster)
set.seed(1234)
split <- rsample::initial_split(points)
train <- rsample::training(split)
test <- rsample::testing(split)
# Fit kmeans on train then assign clusters to test
kclust <- kmeans(train, centers = 3)
clust_centers <- kclust %>%
tidy() %>%
select(-c(size, withinss))
test_clusts <- fuzzyjoin::distance_join(mutate(test, index = row_number()),
clust_centers,
max_dist = Inf,
method = "euclidean",
distance_col = "dist") %>%
group_by(index) %>%
filter(dist == min(dist)) %>%
ungroup()
#> Joining by: c("x1", "x2")
# resulting table
test_clusts
#> # A tibble: 75 x 7
#> x1.x x2.x index x1.y x2.y cluster dist
#> <dbl> <dbl> <int> <dbl> <dbl> <fct> <dbl>
#> 1 4.24 -0.946 1 5.07 -1.10 3 0.847
#> 2 3.54 0.287 2 5.07 -1.10 3 2.06
#> 3 3.71 -1.67 3 5.07 -1.10 3 1.47
#> 4 5.03 -0.788 4 5.07 -1.10 3 0.317
#> 5 6.57 -2.49 5 5.07 -1.10 3 2.04
#> 6 4.97 0.233 6 5.07 -1.10 3 1.34
#> 7 4.43 -1.89 7 5.07 -1.10 3 1.01
#> 8 5.34 -0.0705 8 5.07 -1.10 3 1.07
#> 9 4.60 0.196 9 5.07 -1.10 3 1.38
#> 10 5.68 -1.55 10 5.07 -1.10 3 0.758
#> # ... with 65 more rows
# calc within clusts SS on test
test_clusts %>%
group_by(cluster) %>%
summarise(size = n(),
withinss = sum(dist^2),
withinss_avg = withinss / size)
#> # A tibble: 3 x 4
#> cluster size withinss withinss_avg
#> <fct> <int> <dbl> <dbl>
#> 1 1 11 32.7 2.97
#> 2 2 35 78.9 2.26
#> 3 3 29 62.0 2.14
# compare to on train
tidy(kclust) %>%
mutate(withinss_avg = withinss / size)
#> # A tibble: 3 x 6
#> x1 x2 size withinss cluster withinss_avg
#> <dbl> <dbl> <int> <dbl> <fct> <dbl>
#> 1 -3.22 -1.91 40 76.8 1 1.92
#> 2 0.0993 1.06 113 220. 2 1.95
#> 3 5.07 -1.10 72 182. 3 2.53
# plot of test and train points
test_clusts %>%
select(x1 = x1.x, x2 = x2.x, cluster) %>%
mutate(type = "test") %>%
bind_rows(
augment(kclust, train) %>%
mutate(type = "train") %>%
rename(cluster = .cluster)
) %>%
ggplot(aes(x = x1,
y = x2,
color = as.factor(cluster)))+
geom_point()+
facet_wrap(~fct_rev(as.factor(type)))+
coord_fixed()+
labs(title = "Cluster Assignment on Training and Holdout Datasets",
color = "Cluster")+
theme_bw()
由reprex package (v2.0.0) 于 2021 年 8 月 19 日创建
(有关在 tidymodels 中简化此操作的对话链接,请参阅 OP 评论。)
【讨论】:
以上是关于使用 dplyr 和 broom 在训练和测试集上计算 kmeans的主要内容,如果未能解决你的问题,请参考以下文章
我可以在整个数据集上使用 StandardScaler(),还是应该分别在训练集和测试集上计算?
TensorFlow:神经网络在训练集和测试集上的准确率始终为 100%
R语言plotly可视化:使用plotly可视化简单线性回归模型的回归线使用不同颜色区分训练集和测试集可视化分析模型在测试集上的泛化性能(linear regression plots)
R语言使用caret包的predict函数对模型在测试集上的表现进行推理和预测predict函数对测试数据集进行数据预处理(和训练集的初始方式保持一致):缺失值填充数值变量最小最大缩放独热编码