Использование пакета 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()