Foreach循环无法找到对象 [英] Foreach loop unable to find object

查看:147
本文介绍了Foreach循环无法找到对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用并行后端的foreach加速计算(交叉验证{AUCRF}随机森林进行特征选择,如果这很重要的话)。在这样做的过程中,我需要得到一个向量的子集。矢量的名称可以更改,但可以作为字符矢量访问。我使用了eval(parse())构造(好主意?)来获得vector的一个子集。


$ b 示例:

  library(parallel)
library(foreach)
library(stats)

#create cluster
clu < - makeCluster(detectCores() - 1)
registerDoParallel(clu,cores = detectCores() - 1)

bar< -c(a,b,c在这个例子中,期望的输出是一个包含十个数字的列表,这个列表包含十个数字b,d)
rab <-c(2,3)
bar.name < - bar

#时间
bar [rab]
#或
eval(parse(text = paste(bar.name,[rab],sep =)))

foo< -foreach(m = 1:10,.packages = c(stats))%dopar%{
sink(foreach.txt)
print(bar.name)
print(parse(text = paste(bar.name,[rab],sep =)))
print(eval(parse(text = paste(bar.name,[rab] ),
foo.temp< -eval(parse(text = paste(bar.name,[rab],sep =)))
return( foo.temp)

sink
stopCluster
code $不过我明白了

  {:task 1 failed  - Object'bar'not found中的错误

我以为每个工作人员都得到了所有对象的工作空间副本。任何想法我做错了什么?

解决方案

这听起来像一个糟糕的设计。使用 eval(parse())

为了得到一个变量 get()有点安全,就像 get(bar.name)[rab] 。但是您仍然遇到环境问题。由于在 dopar 中没有变量 bar rab / code>,它们不会被导出到 foreach 运行代码的环境中。你可以通过显式赋值foreach的 .exports = 参数来确定这些变量是否被导出。在这里,我更改为使用 get ,只需显式导出 bar ,因为 rab 现在包含在函数的框中。

  foo <-foreach(m = 1:10,。 export = c(bar),.packages = c(stats))%dopar%{
get(bar.name)[rab]
}

一个比较好的方法不是指定一个变量名,而是指定一个名字列表的元素。例如

  baz < -  list(bar = letters [1:4],bob = letters [5:7]) 

然后您可以做

pre > baz.name< - bar
rab < - c(2,4)

foo < - foreach(m = 1:10,。 packages = c(stats))%dopar%{
baz [[baz.name]] [rab]
}

因为dopar可以看到变量 baz baz.name rab 您不必导出任何东西。


I am trying to use foreach with the parallel backend to speed up computation (of cross validation of an {AUCRF} random forest for feature selection, if this does matter). In the process of doing so i need to get a subset of a vector. The name of the vector can change but is accessible as character vector. I used the eval(parse()) construct(good idea?) to get a subset of the vector.

Example:

library(parallel)
library(foreach)
library(stats)

#create cluster
clu <- makeCluster(detectCores() - 1)
registerDoParallel(clu, cores = detectCores() - 1)

bar<-c("a","b","c","d")
rab<-c(2,3)
bar.name<-"bar"

#expected output in this example is a list containing ten times
bar[rab]
#or
eval(parse(text=paste(bar.name,"[rab]",sep="")))

foo<-foreach(m = 1:10, .packages = c("stats")) %dopar% {
  sink("foreach.txt")
      print(bar.name)
      print(parse(text=paste(bar.name,"[rab]",sep="")))
      print(eval(parse(text=paste(bar.name,"[rab]",sep=""))))
  foo.temp<-eval(parse(text=paste(bar.name,"[rab]",sep="")))
  return(foo.temp)
}
sink()
stopCluster(clu)

However i get the following error:

Error in { : task 1 failed - "Object 'bar' not found"

I thought that each worker is getting a copy of the workspace with all objects. Any idea what I'm doing wrong?

解决方案

This sounds like a bad design. It's almost never necessary to use eval(parse()).

To get a variable, get() is somewhat safer, like get(bar.name)[rab]. But you're still running into an environment issue here. Since you don't have the variables bar or rab in the body of the dopar, they are not exported to the environment where foreach is running the code. You can fix that with an explicit assignment of the .exports= parameter of foreach to make sure those variables are exported. Here I change to use get and only have to explicitly export bar because rab is now include in the box of the function.

foo<-foreach(m = 1:10, .export=c("bar"), .packages = c("stats")) %dopar% {
  get(bar.name)[rab]
}

A better idea would be rather than specifying a variable name, specify an element of a named list. For example

baz <- list(bar=letters[1:4], bob=letters[5:7])

Then you could do

baz.name <- "bar"
rab <- c(2,4)

foo<-foreach(m = 1:10, .packages = c("stats")) %dopar% {
  baz[[baz.name]][rab]
}

And because dopar can see the variables baz, baz.name, and rab you don't have to export anything.

这篇关于Foreach循环无法找到对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆