Foreach и Doparallel вместо L oop в R - PullRequest
3 голосов
/ 01 апреля 2020

Мне нужно ускорить для l oop через многопоточность. Я хотел бы использовать библиотеки для этого: foreach и doParallel . Я использовал эти пакеты раньше, но только для процессов, где нужна была одна таблица результатов. Я не знаю, как использовать их для экспорта нескольких таблиц (здесь таблицы результатов). Моя проблема намного сложнее и требует экспорта множества наборов результатов. Здесь для простоты я использую данные радужной оболочки.

library(randomForest)
library(caret)

results_class <- data.frame()
results_overall <- data.frame()

for(i in 1:50){
  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_class <- rbind(results_class, con.mat_test[["byClass"]])
  results_overall <- rbind(results_overall, con.mat_test[["overall"]])

}

1 Ответ

1 голос
/ 01 апреля 2020

Насколько я знаю, нелегко (или даже возможно) изменять переменные вне foreach l oop, так как насчет сохранения нескольких результатов в одном вложенном tibble?

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

# Set up parallel computing
cl <- makeCluster(detectCores(logical = TRUE))
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")

    # Save output dataframe in tibble as list column
    return(tibble::tibble(iteration = i, 
                          class = list(data.frame(con.mat_test[["byClass"]])), 
                          overall = list(data.frame(con.mat_test[["overall"]]))))
}

# Stop the cluster
stopCluster(cl)
registerDoSEQ()

Вывод будет следующим:

> print(res)
# A tibble: 50 x 2
   class              overall         
   <list>             <list>          
 1 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 2 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 3 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 4 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 5 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 6 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 7 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 8 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
 9 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
10 <df[,11] [3 x 11]> <df[,7] [1 x 7]>
# ... with 40 more rows
...