拆分数据集并将子集并行传递给函数,然后重新组合结果
Posted
技术标签:
【中文标题】拆分数据集并将子集并行传递给函数,然后重新组合结果【英文标题】:Split data set and pass the subsets in parallel to function then recombine the results 【发布时间】:2013-06-25 09:50:30 【问题描述】:这是我尝试使用 foreach 包所做的事情。 我有 600 行和 58000 列的数据集,其中有很多缺失值。
我们需要使用名为“missForest”的包来估算缺失值,其中它不是并行的,一次运行这些数据需要很长时间。
所以,我正在考虑将数据分成 7 个数据集(我有 7 个核心),它们具有相同的行数(我的行)和不同数量的 col(标记)。
然后使用%dopar%
将数据集并行传递给missForest?
我不知道如何将数据划分为更小的数据集并将这些数据集传递给missForest,然后重新组合输出!
如果你能告诉我怎么做,我会非常感激?
这是一个小例子,形成 BLR 包,演示我的问题:
library(BLR)
library(missForest)
data(wheat)
X2<- prodNA(X, 0.1)
dim(X2) ## i need to divide X2 to several 7 data frames (ii)
X3<- missForest(X2)
X3$Ximp ## combine ii data frames
【问题讨论】:
你想做的事情看起来很奇怪。这些列被假定为预测缺失值的变量,因此您可以通过为每个模型使用不同的列来获得非常不同的结果。通常,我会拆分行而不是列! 亲爱的里卡多:谢谢你的好回答,变量在行中。这就是为什么我想除以上校,再次谢谢你 好的。那么,也许你应该先转置,呵呵。 【参考方案1】:在并行处理大型矩阵时,仅传递每个集群工作程序所需的数据可能非常重要。在 Linux 上直接或间接使用 mclapply
时,这不是问题。但是在 Windows 上,输入数据是通过套接字连接发送到集群工作人员的,因此它可能非常重要。
对于这种情况,我使用itertools
包中的isplitCol
函数。它在矩阵的列块上创建一个迭代器。使用chunks
参数,您可以拆分矩阵,以便每个集群工作人员获得一个子矩阵。
这是您的示例到 foreach
的翻译,它使用 isplitCol
将输入矩阵拆分为 7 个子矩阵,因此与将 X2
自动导出到每个工作人员相比,发送给每个工作人员的数据减少了七倍工人:
library(doParallel)
library(itertools)
library(BLR)
library(missForest)
ncores <- 7
cl <- makePSOCKcluster(ncores)
registerDoParallel(cl)
data(wheat)
X2 <- prodNA(X, 0.1)
X3 <- foreach(m=isplitCols(X2, chunks=ncores), .combine='cbind',
.packages='missForest') %dopar%
missForest(m)$ximp
print(X3)
stopCluster(cl)
【讨论】:
如何为包含 36 个变量和 287 000 条记录的数据框选择核数?谢谢!【参考方案2】:library(multicore)
n.cores <- 7
cuts <- cut(1:ncol(X2), n.cores)
X3 <- mclapply(levels(cuts), function(x)
missForest(X2[, cuts == x])$ximp , mc.cores=n.cores)
X3 <- do.call(cbind, X3)
cut 将列拆分为 7 个间隔,然后 mclapply 发送到您的 7 个核心。最后将它们全部绑定在一起
编辑:添加我的 foreach 实现。注意:我以前从未使用过这个包,但它似乎在做我期望的事情
library(doParallel)
library(foreach)
n.cores <- 7
cuts <- cut(1:ncol(X2), n.cores)
cl <- makeCluster(n.cores)
registerDoParallel(cl)
X3 <- foreach(x=levels(cuts), .combine=cbind, .multicombine=TRUE) %dopar%
library(missForest); missForest(X2[, cuts == x])$ximp
【讨论】:
对不起,我没有使用 foreach。我发现这种方式更简单,更快。目前正在测试/运行我的 foreach 实现... 嗨杰克:谢谢你回答我的问题。我正在尝试在我的 PC“Win7 和 R 15.2”上安装多核,R 一直告诉我它不适用于此版本??知道我该怎么做吗?再次感谢 @hemamulticore
软件包从未在 Windows 上可用。尽管mclapply
在 Windows 上的 parallel
包中可用,但它不会并行运行,因此对您没有多大好处。
@hema 我添加了一个 foreach 实现,但是,正如我在注释中提到的,这是我第一次使用 foreach。它似乎确实符合我的预期(通过检查 X3 和 X2 的列名,并随机查看两个矩阵的区域)。【参考方案3】:
您必须将矩阵拆分为ncores
部分,然后再次组合它们。由于您使用的是随机森林,因此您可以随机拆分数据(并执行多次以检查和验证结果)。
ncores = 7
split = sample(seq(ncores), size=ncol(X2), replace=TRUE) # random partitioning
X3 = foreach(i=seq_len(ncores), .combine=cbind, .inorder=FALSE) %dopar%
ind = which(split==i) # the selected rows for this core
X = rbind(ind, missForest(X2[,ind])$ximp) # add the index as first row!
ind = X3[1,] # get all the index back
ind = sort(ind, index.return=TRUE)$ix # sort the index to recover the original row order
X3 = X3[-1,ind] # remove the index
【讨论】:
:OP 正在使用missForest
包,它专注于缺失值而不是随机森林
@Metrics:missForest 包使用随机森林 (?missForest)。随机森林是一种机器学习技术,而不是 R 包:en.wikipedia.org/wiki/Random_forest
:我用过randomForest :)以上是关于拆分数据集并将子集并行传递给函数,然后重新组合结果的主要内容,如果未能解决你的问题,请参考以下文章