Подтвердить что ты не робот

Полностью воспроизводимые параллельные модели с использованием каретки

Когда я запускаю 2 случайных леса в карете, я получаю точные результаты, если я устанавливаю случайное семя:

library(caret)
library(doParallel)

set.seed(42)
myControl <- trainControl(method='cv', index=createFolds(iris$Species))

set.seed(42)
model1 <- train(Species~., iris, method='rf', trControl=myControl)

set.seed(42)
model2 <- train(Species~., iris, method='rf', trControl=myControl)

> all.equal(predict(model1, type='prob'), predict(model2, type='prob'))
[1] TRUE

Однако, если я зарегистрирую параллельный back-end для ускорения моделирования, я получаю другой результат каждый раз, когда запускаю модель:

cl <- makeCluster(detectCores())
registerDoParallel(cl)

set.seed(42)
myControl <- trainControl(method='cv', index=createFolds(iris$Species))

set.seed(42)
model1 <- train(Species~., iris, method='rf', trControl=myControl)

set.seed(42)
model2 <- train(Species~., iris, method='rf', trControl=myControl)

stopCluster(cl)

> all.equal(predict(model1, type='prob'), predict(model2, type='prob'))
[1] "Component 2: Mean relative difference: 0.01813729"
[2] "Component 3: Mean relative difference: 0.02271638"

Есть ли способ исправить эту проблему? Одно из предложений заключалось в использовании пакета doRNG, но train использует вложенные циклы, которые в настоящее время не поддерживаются:

library(doRNG)
cl <- makeCluster(detectCores())
registerDoParallel(cl)
registerDoRNG()

set.seed(42)
myControl <- trainControl(method='cv', index=createFolds(iris$Species))

set.seed(42)
> model1 <- train(Species~., iris, method='rf', trControl=myControl)
Error in list(e1 = list(args = seq(along = resampleIndex)(), argnames = "iter",  : 
  nested/conditional foreach loops are not supported yet.
See the package vignette for a work around.

UPDATE: Я думал, что эта проблема может быть решена с помощью doSNOW и clusterSetupRNG, но я не мог туда добраться.

set.seed(42)
library(caret)
library(doSNOW)
cl <- makeCluster(8, type = "SOCK")
registerDoSNOW(cl)

myControl <- trainControl(method='cv', index=createFolds(iris$Species))

clusterSetupRNG(cl, seed=rep(12345,6))
a <- clusterCall(cl, runif, 10000)
model1 <- train(Species~., iris, method='rf', trControl=myControl)

clusterSetupRNG(cl, seed=rep(12345,6))
b <- clusterCall(cl, runif, 10000)
model2 <- train(Species~., iris, method='rf', trControl=myControl)

all.equal(a, b)
[1] TRUE
all.equal(predict(model1, type='prob'), predict(model2, type='prob'))
[1] "Component 2: Mean relative difference: 0.01890339"
[2] "Component 3: Mean relative difference: 0.01656751"

stopCluster(cl)

Что особенного в foreach, и почему он не использует семена, которые я начал в кластере? объекты a и b идентичны, поэтому почему бы не model1 и model2?

4b9b3361

Ответ 1

Один простой способ запуска полностью воспроизводимой модели в параллельном режиме с использованием пакета caret заключается в использовании аргумента seed при вызове управления поездами. Здесь приведенный выше вопрос разрешен, проверьте страницу справки trainControl для получения дополнительной информации.

library(doParallel); library(caret)

#create a list of seed, here change the seed for each resampling
set.seed(123)

#length is = (n_repeats*nresampling)+1
seeds <- vector(mode = "list", length = 11)

#(3 is the number of tuning parameter, mtry for rf, here equal to ncol(iris)-2)
for(i in 1:10) seeds[[i]]<- sample.int(n=1000, 3)

#for the last model
seeds[[11]]<-sample.int(1000, 1)

 #control list
 myControl <- trainControl(method='cv', seeds=seeds, index=createFolds(iris$Species))

 #run model in parallel
 cl <- makeCluster(detectCores())
 registerDoParallel(cl)
 model1 <- train(Species~., iris, method='rf', trControl=myControl)

 model2 <- train(Species~., iris, method='rf', trControl=myControl)
 stopCluster(cl)

 #compare
 all.equal(predict(model1, type='prob'), predict(model2, type='prob'))
[1] TRUE

Ответ 2

Таким образом, каретка использует пакет foreach для распараллеливания. Скорее всего, есть способ установить семя на каждой итерации, но нам нужно настроить дополнительные параметры в train.

В качестве альтернативы вы можете создать пользовательскую функцию моделирования, которая имитирует внутреннюю для случайных лесов и сама выберет семя.

Max