Использование пакета parallelMap с пользовательским фильтром в мл

Я работаю с MLR, чтобы сделать задачу классификации текста. Я написал собственный фильтр, как описано здесь

Создать пользовательские фильтры

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

Exporting objects to slaves for mode socket: .mlr.slave.options
Mapping in parallel: mode = socket; cpus = 4; elements = 2.
Error in stopWithJobErrorMessages(inds, vcapply(result.list[inds], as.character)) : 
  Errors occurred in 2 slave jobs, displaying at most 10 of them:

00001: Error in parallel:::.slaveRSOCK() : 
  Assertion on 'method' failed: Must be element of set {'anova.test','carscore','cforest.importance','chi.squared','gain.ratio','information.gain','kruskal.test','linear.correlation','mrmr','oneR','permutation.importance','randomForest.importance','randomForestSRC.rfsrc','randomForestSRC.var.select','rank.correlation','relief','rf.importance','rf.min.depth','symmetrical.uncertainty','univariate','univariate.model.score','variance'}.

Исходя из ошибки, я предполагаю, что мой пользовательский фильтр должен быть элементом в наборе, чтобы иметь шанс работать параллельно, но мне не удалось выяснить, если (а) это возможно, и (б), если он есть, как мне это сделать.

Заранее спасибо за любую помощь, Азам

Добавлено: Тестовый скрипт. Я не могу позволить вам увидеть фактический скрипт / данные, с которыми я работаю, из-за чувствительности, но этот пример воспроизводит ошибку, которую я вижу. Помимо выбора пользовательских функций и набора данных, шаги по настройке ученика и его оценке такие же, как в моем "реальном" сценарии. Как и в моем реальном случае, если вы удалите команду parallelStartSocket(), тогда скрипт будет работать как положено.

Я также должен добавить, что я успешно использовал (или, по крайней мере, не получил ошибок) параллельную обработку при настройке гиперпараметров SVM с ядром RBF: сценарий идентичен, кроме определения makeParamSet().

library(parallelMap)
library(mlr)
library(kernlab)

makeFilter(
  name = "nonsense.filter",
  desc = "Calculates scores according to alphabetical order of features",
  pkg = "mlr",
  supported.tasks = c("classif", "regr", "surv"),
  supported.features = c("numerics", "factors", "ordered"),
  fun = function(task, nselect, decreasing = TRUE, ...) {
    feats = getTaskFeatureNames(task)
    imp = order(feats, decreasing = decreasing)
    names(imp) = feats
    imp
  }
)

# set up svm with rbf kernal
svm.lrn <- makeLearner("classif.ksvm",predict.type = "response")  

# wrap learner with filter
svm.lrn <- makeFilterWrapper(svm.lrn, fw.method = "nonsense.filter")

# define feature selection parameters 

ps.svm = makeParamSet(
  makeDiscreteParam("fw.abs", values = seq(2, 3, 1)) 

)

# define inner search and evaluation strategy
ctrl.svm = makeTuneControlGrid()
inner.svm = makeResampleDesc("CV", iters = 5, stratify = TRUE)

svm.lrn <- makeTuneWrapper(svm.lrn, resampling = inner.svm, par.set = ps.svm, 
                           control = ctrl.svm)

# set up outer resampling
outer.svm <-  makeResampleDesc("CV", iters = 10, stratify = TRUE)

# run it...

parallelStartSocket(2)

run.svm <- resample(svm.lrn, iris.task, 
                    resampling = outer.svm, extract = getTuneResult)

parallelStop()

1 ответ

Решение

Проблема в том, что makeFilter регистрирует методы S3, которые недоступны в отдельных процессах R. У вас есть два варианта сделать это: либо просто использовать parallelStartMulticore(2) так что все работает в одном и том же процессе R, или сказать parallelMap о частях, которые должны присутствовать в других процессах R.

Последний состоит из двух частей. Во-первых, используйте parallelLibrary("mlr") везде загрузить mlr и вытащить определение фильтра в отдельный файл, который можно загрузить с помощью parallelSource(), Например:

filter.R:

makeFilter(
  name = "nonsense.filter",
  desc = "Calculates scores according to alphabetical order of features",
  pkg = "mlr",
  supported.tasks = c("classif", "regr", "surv"),
  supported.features = c("numerics", "factors", "ordered"),
  fun = function(task, nselect, decreasing = TRUE, ...) {
    feats = getTaskFeatureNames(task)
    imp = order(feats, decreasing = decreasing)
    names(imp) = feats
    imp
  }
)

main.R:

library(parallelMap)
library(mlr)
library(kernlab)

parallelStartSocket(2)

parallelLibrary("mlr")
parallelSource("filter.R")

# set up svm with rbf kernal
svm.lrn = makeLearner("classif.ksvm",predict.type = "response")  

# wrap learner with filter
svm.lrn = makeFilterWrapper(svm.lrn, fw.method = "nonsense.filter")

# define feature selection parameters 

ps.svm = makeParamSet(
  makeDiscreteParam("fw.abs", values = seq(2, 3, 1)) 

)

# define inner search and evaluation strategy
ctrl.svm = makeTuneControlGrid()
inner.svm = makeResampleDesc("CV", iters = 5, stratify = TRUE)

svm.lrn = makeTuneWrapper(svm.lrn, resampling = inner.svm, par.set = ps.svm, 
                           control = ctrl.svm)

# set up outer resampling
outer.svm =  makeResampleDesc("CV", iters = 10, stratify = TRUE)

# run it...
run.svm = resample(svm.lrn, iris.task, resampling = outer.svm, extract = getTuneResult)

parallelStop()
Другие вопросы по тегам