【问题标题】:How to get same results using loop and parallel in R?如何在 R 中使用循环和并行获得相同的结果?
【发布时间】:2020-08-15 07:17:13
【问题描述】:

我测试了训练数据对分类准确性的影响。例如,我使用虹膜数据。我注意到我从 33 次迭代中获得了最佳精度。我想使用迭代中的训练集(iristrain)进行进一步分析。我不知道如何重现它。我不想每次迭代都保存训练集,因为它很大。我只想从 33 次迭代中得到这个集合。 我试过这个: clusterSetRNGStream() 然后我在一个循环中使用了相同的种子,它没有给出相同的结果

library(randomForest)
library(caret)
library(foreach)
library(doParallel)

results_overall <- data.frame()

cores = detectCores()
cl = makeCluster(cores - 1)

registerDoParallel(cl)
res <- foreach(i = 1:50, .packages = c("caret", "randomForest"), .combine = rbind) %dopar% {

trainIndex <- caret::createDataPartition(iris$Species, p = 0.5, list = FALSE)
irisTrain <- iris[ trainIndex,]
irisTest  <- iris[-trainIndex,]

model <- randomForest(x = irisTrain[,c(1:4)], y = irisTrain[,5], importance = TRUE,
                                            replace = TRUE, mtry = 4, ntree = 500, na.action=na.omit,
                                            do.trace = 100, type = "classification")

pred_test <- predict(model, irisTest[,c(1:4)])
con.mat_test <- confusionMatrix(pred_test, irisTest[,5], mode ="everything")

results_overall <- rbind(results_overall, con.mat_test[["overall"]])

return(tibble::tribble(~iteration, ~overall, 
                       i, results_overall))
}
stopCluster(cl)

【问题讨论】:

    标签: r foreach parallel-processing r-caret doparallel


    【解决方案1】:

    您的迭代根据caret::createDataPartition 执行的随机抽样给出了差异。为了使这个可重现,您可以使用为此目的编写的 doRNG 包 - 非常感谢 @HenrikB 对我的启发!

    编辑:修复了foreach函数 (没有改变结果)

    invisible(suppressPackageStartupMessages(
        lapply(c("data.table", "randomForest", "caret", "foreach", 
                 "doRNG", "rngtools", "doParallel"),
               require, character.only = TRUE)))
    cores = detectCores()
    cl = makeCluster(cores - 1)
    registerDoParallel(cl)
    res <- foreach(i = 1:50, .packages = c("caret", "randomForest", "data.table"), .combine = rbind,
                   .options.RNG=1234) %dorng% {
                       trainIndex <- caret::createDataPartition(iris$Species, p = 0.5, list = FALSE)
                       irisTrain <- iris[ trainIndex,]
                       irisTest  <- iris[-trainIndex,]
                       model <- randomForest(x = irisTrain[,c(1:4)], y = irisTrain[,5], importance = TRUE,
                                             replace = TRUE, mtry = 4, ntree = 500, na.action=na.omit,
                                             do.trace = 100, type = "classification")
                       pred_test <- predict(model, irisTest[,c(1:4)])
                       con.mat_test <- confusionMatrix(pred_test, irisTest[,5], mode ="everything")
                       return(data.table(Iteration=i, t(con.mat_test[["overall"]])))
                   }
    stopCluster(cl)
    seeds <-  attr(res, 'rng')
    res[which.min(Accuracy),]
    #>    Iteration  Accuracy Kappa AccuracyLower AccuracyUpper AccuracyNull
    #> 1:         6 0.9066667  0.86     0.8171065     0.9616461    0.3333333
    #>    AccuracyPValue McnemarPValue
    #> 1:    4.39803e-25           NaN
    
    best.seed <- res[which.min(Accuracy),]$Iteration
    
    rngtools::setRNG(seeds[[best.seed]])
    trainIndex <- caret::createDataPartition(iris$Species, p = 0.5, list = FALSE)
    irisTrain <- iris[ trainIndex,]
    irisTest  <- iris[-trainIndex,]
    
    model <- randomForest(x = irisTrain[,c(1:4)], y = irisTrain[,5], importance = TRUE,
                          replace = TRUE, mtry = 4, ntree = 500, na.action=na.omit,
                          do.trace = 100, type = "classification")
    #> ntree      OOB      1      2      3
    #>   100:   4.00%  0.00%  4.00%  8.00%
    #>   200:   2.67%  0.00%  4.00%  4.00%
    #>   300:   2.67%  0.00%  4.00%  4.00%
    #>   400:   2.67%  0.00%  4.00%  4.00%
    #>   500:   4.00%  0.00%  4.00%  8.00%
    pred_test <- predict(model, irisTest[,c(1:4)])
    con.mat_test <- confusionMatrix(pred_test, irisTest[,5], mode ="everything")
    con.mat_test[["overall"]]
    #>       Accuracy          Kappa  AccuracyLower  AccuracyUpper   AccuracyNull 
    #>   9.066667e-01   8.600000e-01   8.171065e-01   9.616461e-01   3.333333e-01 
    #> AccuracyPValue  McnemarPValue 
    #>   4.398030e-25            NaN
    

    reprex package (v0.3.0) 于 2020-05-05 创建

    【讨论】:

    • 使用set.seed(i) 是一种常见的习惯,但不幸的是,它在统计上并不可靠。您最终可能会得到相关的随机数,这反过来又会给您带来有偏差的结果。适当的并行 RNG 本身就是一个研究课题。
    • 更好的解决方案是使用doRNG 包,它可以为您提供统计上可靠的RNG(也是并行的)。您需要做的就是library(doRNG),然后将%dopar% 替换为%dorng%。有关更多信息和示例,请参阅 help("%dorng%", package="doRNG")
    • @HenrikB - 非常感谢您的建议,这非常有用;我已经修改了我的帖子并合并了doRNG 方法。
    • 我只会问为什么使用它:invisible (suppressPackageStartupMessages()... ?
    • 很遗憾,我没有检查 foreach 函数的内容。解决了这个问题。结果保持不变。
    【解决方案2】:

    试试这个set.seed(1) 并将它设置在training 模型之前。有关更多信息,请致电R 这个命令?set.seed(),那里描述得很好。 seed number 是生成随机数序列的起点。欲了解更多信息here

    【讨论】:

      猜你喜欢
      • 2019-03-06
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2012-06-01
      相关资源
      最近更新 更多