Modelos paralelos completamente reproducibles utilizando el cursor

Cuando ejecuto 2 bosques aleatorios en caret, obtengo exactamente los mismos resultados si configuro una semilla aleatoria:

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  all.equal(predict(model1, type='prob'), predict(model2, type='prob')) [1] TRUE 

Sin embargo, si registro un back-end paralelo para acelerar el modelado, obtengo un resultado diferente cada vez que ejecuto el modelo:

 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  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" 

¿Hay alguna manera de arreglar este problema? Una sugerencia fue utilizar el paquete doRNG , pero train utiliza bucles nesteds, que actualmente no son compatibles:

 library(doRNG) cl <- makeCluster(detectCores()) registerDoParallel(cl) registerDoRNG() set.seed(42) myControl  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's vignette for a work around. 

ACTUALIZACIÓN: pensé que este problema podría resolverse utilizando doSNOW y clusterSetupRNG , pero no pude llegar allí.

 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) 

¿Qué tiene de especial foreach, y por qué no usa las semillas que inicié en el clúster? los objetos a y b son idénticos, ¿por qué no model1 y model2 ?

Una forma fácil de ejecutar un modelo completamente reproducible en modo paralelo utilizando el paquete caret es usar el argumento de semillas al llamar al control del tren. Aquí se resuelve la pregunta anterior, consulte la página de ayuda de trainControl para obtener más información.

 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 

Entonces, caret usa el paquete foreach para paralelizar. Probablemente haya una manera de establecer la semilla en cada iteración, pero tendríamos que configurar más opciones en el train .

Alternativamente, puede crear una función de modelado personalizada que imite la función interna para bosques aleatorios y establecer la semilla usted mismo.

Max

    Intereting Posts