R dismo :: gbm.step并行参数选择函数

时间:2015-04-26 04:03:29

标签: r loops parallel-processing r-caret gbm

我有一个工作函数,它被编码以优化并行处理(希望如此)。我仍然不是最熟练的R,尤其是函数和迭代。

我希望有人可以帮助我优化我编写的功能以及额外的代码,以帮助计算时间并完全优化并行处理选项。

具体使用%do% vs %dopar%并移动函数内的附加代码和并行处理函数。我似乎无法让%dopar%工作,我不确定这是我的代码,R版本或冲突库的问题。

我非常感谢关于以更有效的方式获得相同结果的可能方法的任何建议。

背景

我正在使用dismo::gbm.step来构建gbm模型。 gbm.step通过k折交叉验证选择最佳树数。但是,仍然需要设置树复杂度和学习速率的参数。我知道caret::train是专为此任务而构建的,我在学习caret方面有很多乐趣,特别是它的自适应重采样功能。但是,我的回答是二项式的,caret没有选择返回二项式分布的AUC;我想使用AUC在我的领域(生态学)复制类似的已发表的研究。

我也在后面的分析中使用dismo::gbm.simplify来识别可能的简化模型。 gbm.simplify依赖于在dismo中构建模型时创建的数据,而我无法使其在caret中构建的模型上运行。

最后,生态学中的大多数gbm文献都遵循Elith等人描述的方法。 2008" A working guide to boosted regression trees",这是dismo中BRT功能的基础。出于本研究的目的,我希望继续使用dismo来构建gbm模型。

我编写的函数测试了tree.complexitylearning.rate的几种组合,并返回每个模型的几个性能指标的列表。然后我将所有lists合并到data.frame中以便于排序。

该功能的目标

  1. gbm和的每次迭代创建tree.complexity模型 learning.rate
  2. 存储$self.statistics$discriminationcv.statistics$discrimination.meanself.statistics$mean.resid, 每个cv.statistics$deviance.mean模型的list中都有gbm 创建。
  3. 删除每个gbm模型以节省空间。
  4. 将每个列表组合在一起,形成一种便于排序的格式。然后删除每个列表。
  5. 以优化并行处理以及减少计算时间和使用内存的方式执行上述所有操作。
  6. 可重复的示例 使用Anguilla_train

    中的dismo数据集
    #Load libraries
    require(pacman)
    p_load(gbm, dismo, TeachingDemos, foreach, doParallel, data.table) 
    
    data(Anguilla_train)
    
    #Identify cores on current system
    cores<-detectCores(all.tests = FALSE, logical = FALSE)
    cores
    
    #Create training function for gbm.step
    step.train.fx=function(tree.com,learn){
      #set seed for reproducibility
      char2seed("StackOverflow", set = TRUE)
      k1<-gbm.step(data=Anguilla_train, 
                   gbm.x = 3:13, 
                   gbm.y = 2,
                   family = "bernoulli", 
                   tree.complexity = tree.com,
                   learning.rate = learn,
                   bag.fraction = 0.7,
                   prev.stratify=TRUE,
                   n.folds=10,
                   n.trees=700,
                   step.size=25,
                   silent=TRUE,
                   plot.main = FALSE,
                   n.cores=cores)
    
      k.out=list(interaction.depth=k1$interaction.depth,
                 shrinkage=k1$shrinkage,
                 n.trees=k1$n.trees,
                 AUC=k1$self.statistics$discrimination,
                 cv.AUC=k1$cv.statistics$discrimination.mean,
                 deviance=k1$self.statistics$mean.resid,
                 cv.deviance=k1$cv.statistics$deviance.mean)  
      return(k.out)
    }
    
    #define complexity and learning rate
    tree.complexity<-c(1:5)
    learning.rate<-c(0.01,0.025,0.005,0.0025,0.001)
    
    #setup parallel backend to use n processors
    cl<-makeCluster(cores)
    registerDoParallel(cl)
    
    #Run the actual function
    foreach(i = tree.complexity) %do% {
      foreach(j = learning.rate) %do% {
        nam=paste0("gbm_tc",i,"lr",j)
        assign(nam,step.train.fx(tree.com=i,learn=j))
    
      }
    }
    
    #Stop parallel
    stopCluster(cl)
    registerDoSEQ()
    
    #disable scientific notation
    options(scipen=999)
    
    #Find all item in workspace that contain "gbm_tc"
    train.all<-ls(pattern="gbm_tc")
    
    #cbind each list that contains "gbm_tc"
    train.results<-list(do.call(cbind,mget(train.all)))
    
    #Place in a data frame
    train.results<- do.call(rbind, lapply(train.results, rbind))
    train.results <- data.frame(matrix(unlist(train.results),ncol=7 , byrow=T))
    
    #Change column names
    colnames(train.results)<-c("TC","LR","n.trees", "AUC", "cv.AUC", "dev", "cv.dev")
    
    #Round 4:7
    train.results[,4:7]<-round(train.results[,4:7],digits=3)
    
    #Sort by cv.dev, cv.AUC, AUC
    train.results<-train.results[order(train.results$cv.dev,-train.results$cv.AUC, -train.results$AUC),]
    
    train.results
    

1 个答案:

答案 0 :(得分:0)

我还在努力弄清楚自己该怎么做,而且你比我更进一步!我遇到的一件事是问题可能出现在嵌套的%do%中?作为测试,为什么不仅仅为%dopar%尝试j,或者看看您是否可以崩溃j&amp;将k矩阵转换为单个向量,可能包含两个术语排列的列表,传递给gbm.step? E.g。

tree.complexity = i[1],
learning.rate = i[2],

如果你有任何成功,请告诉我!

编辑:另外,另一条潜在路线是来自here%:%

foreach(tree.com = 1:5) %:% foreach(learn = c(0.01,0.025,0.005,0.0025,0.001)) %dopar% {
gbm.step ... return(list(...))}

如果您添加了tree.com&amp; learn到列表然后可能会吐出这些值的漂亮矩阵。另一种选择:

foreach(tree.com = 1:5, learn = c(0.01,0.025,0.005,0.0025,0.001) %dopar% {
    gbm.step ... return(list(...))}