Проблема с использованием пользовательской функции сводки в параллельном выполнении (курсор вставки)

Я пытаюсь использовать MAPE в качестве метрики для оценки производительности модели.

В случае LOOCV и параллельного выполнения все работает правильно, но если я использую другой метод повторной выборки, я получаю эту ошибку:

Ошибка в {: задача 1 не удалась — «не удалось найти функцию «mape»»

Вместо этого в последовательном исполнении эта проблема исчезает.

В приведенном ниже коде приведен пример.

    library(caret)
    library(doParallel)

    data("environmental")

    registerDoParallel(makeCluster(detectCores(), outfile = ''))



    mape <- function(y, yhat) mean(abs((y - yhat)/y))

    mapeSummary <- function (data, lev = NULL, model = NULL) {

                       out <- mape(data$obs, data$pred)
                       names(out) <- "MAPE"

                       out
                     }



    #LOOCV - parallel
    trControlLoocvPar <- trainControl(allowParallel = T,
                                      verboseIter = T, 
                                      method = "LOOCV",
                                      summaryFunction = mapeSummary)

    #LOOCV - serial
    trControlLoocvSer <- trainControl(allowParallel = F,
                                      verboseIter = T, 
                                      method = "LOOCV",
                                      summaryFunction = mapeSummary)

    #Bootstrapping - parallel
    trControlBootPar <- trainControl(allowParallel = T,
                                      verboseIter = T, 
                                      method = "boot",
                                      summaryFunction = mapeSummary)

    #Bootstrapping - serial
    trControlBootSer <- trainControl(allowParallel = F,
                                      verboseIter = T, 
                                      method = "boot",
                                      summaryFunction = mapeSummary)


    trControlList <- list(trControlLoocvSer, 
                          trControlLoocvPar,
                          trControlBootSer,
                          trControlBootPar)


    models <- lapply(trControlList, 
                     function(control) {

                       train(y = environmental$ozone,
                       x = environmental[, -1], 
                       method = "glmnet", 
                       trControl = control, 
                       metric = "MAPE", 
                       maximize = FALSE)
                     })

Моя ОС — El Capitan 10.11.4, а версия Caret — 6.0.62.


person amarchin    schedule 04.05.2016    source источник


Ответы (1)


Как говорится в сообщении, ваши параллельные процессы не могут найти функцию mape.

Самое простое решение — поместить функцию mape в функцию mapeSummary, как показано ниже. Тогда ваши параллельные процессы будут работать корректно.

mapeSummary <- function (data, lev = NULL, model = NULL) {
  mape <- function(y, yhat) mean(abs((y - yhat)/y))
  out <- mape(data$obs, data$pred)
  names(out) <- "MAPE"

  out
}

бонус:

Вы также можете использовать функцию clusterEvalQ, одну из функций clusterApply. Это работает так, как показано ниже, но это не самое элегантное решение и требует больше ввода:

cl <- makePSOCKcluster(detectCores()-1)
clusterEvalQ(cl, mape <- function(y, yhat) mean(abs((y - yhat)/y)))
registerDoParallel(cl)

mapeSummary <- function (data, lev = NULL, model = NULL) {
   out <- mape(data$obs, data$pred)
  names(out) <- "MAPE"
  out
}

#Bootstrapping - parallel
trControlBootPar <- trainControl(allowParallel = T,
                                 verboseIter = T, 
                                 method = "boot",
                                 summaryFunction = mapeSummary)

train(y = environmental$ozone,
      x = environmental[, -1], 
      method = "glmnet", 
      trControl = trControlBootPar, 
      metric = "MAPE", 
      maximize = FALSE)

stopCluster(cl)
registerDoSEQ()
person phiver    schedule 04.05.2016