【问题标题】:nlsBoot and foreach %dopar%: scoping issuesnlsBoot 和 foreach %dopar%:范围问题
【发布时间】:2012-11-14 17:22:06
【问题描述】:

我想对nls 的残差进行引导,使其适合循环。我使用nlsBoot,为了减少计算时间,我想并行执行(目前在 Windows 7 系统上)。这是一些代码,它重现了我的问题:

#function for fitting
Falge2000 <- function(GP2000,alpha,PAR) {
  (GP2000*alpha*PAR)/(GP2000+alpha*PAR-GP2000/2000*PAR)
}

#some data
PAR <- 10:1600
GPP <- Falge2000(-450,-0.73,PAR) + rnorm(length(PAR),sd=0.0001)
df1 <- data.frame(PAR,GPP)

#nls fit
mod <- nls(GPP~Falge2000(GP2000,alpha,PAR),start=list(GP2000=-450,alpha=-0.73),data=df1, upper=c(0,0),algorithm="port")

#bootstrap of residuals
library(nlstools)
summary(nlsBoot(mod,niter=5))
#works

#now do it several times
#and in parallel
library(foreach)
library(doParallel)

cl <- makeCluster(1)
registerDoParallel(cl)

ttt <- foreach(1:5, .packages='nlstools',.export="df1") %dopar% {
  res <- nlsBoot(mod,niter=5)
  summary(res)

}
#Error in { : 
#task 1 failed - "Procedure aborted: the fit only converged in 1 % during bootstrapping"

stopCluster(cl)

我怀疑这是环境问题,在查看 nlsBoot 的代码后,问题似乎是由于在 lapply 调用中使用匿名函数引起的:

l1 <- lapply(1:niter, function(i) {
    data2[, var1] <- fitted1 + sample(scale(resid1, scale = FALSE), 
        replace = TRUE)
    nls2 <- try(update(nls, start = as.list(coef(nls)), data = data2), 
        silent = TRUE)
    if (inherits(nls2, "nls")) 
        return(list(coef = coef(nls2), rse = summary(nls2)$sigma))
})
if (sum(sapply(l1, is.null)) > niter/2) 
    stop(paste("Procedure aborted: the fit only converged in", 
        round(sum(sapply(l1, is.null))/niter), "% during bootstrapping"))

有没有办法在并行循环中使用nlsBoot?还是我需要修改功能? (我可以尝试使用for 循环而不是lapply。)

【问题讨论】:

  • 您是否尝试过在%dopar% 循环中创建mod 对象(而不是自动导出)?

标签: r foreach scope nls statistics-bootstrap


【解决方案1】:

通过将 mod 对象的创建移到 %dopar% 循环中,看起来一切正常。此外,这会自动导出 df1 对象,因此您可以删除 .export 参数。

ttt <- foreach(1:5, .packages='nlstools') %dopar% {
  mod <- nls(GPP~Falge2000(GP2000,alpha,PAR),start=list(GP2000=-450,alpha=-0.73),data=df1, upper=c(0,0),algorithm="port")
  res <- nlsBoot(mod,niter=5)
  capture.output(summary(res))

}

但是,您可能需要确定要返回的内容。使用capture.output 只是为了看看事情是否正常,因为summary(res) 似乎只返回NULL

【讨论】:

  • 谢谢。虽然这适用于简化示例,但不适用于我的实际问题。我最终将nlsBoot 的代码从函数中取出,并在仅返回系数的过程中对其进行了一些简化。
猜你喜欢
  • 1970-01-01
  • 2011-04-23
  • 2014-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-13
  • 2011-10-11
  • 1970-01-01
相关资源
最近更新 更多