R foreach параллельная обработка с неэкспортированными функциями (на примере C50)

Я пытаюсь извлечь правила из модели C50 при параллельной обработке. Этот ответ помог мне извлечь правила из объекта модели. Однако, поскольку мне нужно, чтобы модели обрабатывались параллельно, я использую foreach. Кажется, это проблема с неэкспортируемой функцией, так как она не видит объект данных. Вот некоторый воспроизводимый код:

library(foreach)
library(doMC)
registerDoMC(2)

j = c(1,2)
result = foreach(i = j) %dopar% {
  library(C50)
  d = iris
  model <- C5.0(Species ~ ., data = d)
  modParty <- C50:::as.party.C5.0(model)
  return(modParty)
}

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

Моя отладка показала, что разная строка modParty <- C50:::as.party.C5.0(model). Выдает ошибку

Ошибка в {: задача 1 не удалась - «Объект 'd' не найден»

даже если d наверняка доступен для каждого воркера в кластере. Я проверил это с логом в файл через loginfo(ls()) пакета logging.

Почему функция не видит объект d? Любая помощь очень ценится.

В качестве дополнительной информации здесь traceback()

> traceback()
3: stop(simpleError(msg, call = expr))
2: e$fun(obj, substitute(ex), parent.frame(), e$data)
1: foreach(i = j) %dopar% {
       library(C50)
       d = iris
       model <- C5.0(Species ~ ., data = d)
       modParty <- C50:::as.party.C5.0(model)
       return(modParty)
   }

Изменить

Просто для уточнения: это ничего не должно делать с foreach. Это та же ошибка с нормальной функцией:

library(C50)

d = iris

getC50Party = function(dat){
  model <- C5.0(Species ~ ., data = dat)
  modParty <- C50:::as.party.C5.0(model)
  return(modParty)
}

c50Party = getC50Party(d)

Ошибка в {: задача 1 не удалась - «Объект 'dat' не найден»

Проблема в том, что as.party.C5.0 пытается получить доступ к объекту данных из общей рабочей области.


person Jonny    schedule 29.05.2016    source источник
comment
Я не уверен, что именно здесь происходит, потому что partykit (в соавторстве с которым я) вообще не участвует. Все сводится к тому, что пакет C50 делает со своими моделями. Моя предварительная оценка состоит в том, что C5.0 объекты должны лучше сохранять свои terms, а не перестраивать их внутри метода as.party. Но я действительно не копал достаточно глубоко в этом. Поскольку сопровождающий C50, похоже, в данный момент не следует SO, я бы порекомендовал связаться с ним напрямую по этому поводу. Но, возможно, метод as.party не экспортируется по какой-то причине...   -  person Achim Zeileis    schedule 30.05.2016
comment
да, похоже так. Потому что метод as.party.C5.0 пытается обратиться к d не из объекта model, а из общего рабочего пространства (даже не из рабочего пространства воркера). Я уже написал Максу по электронной почте и отправил ему ссылку на вопрос SO. К сожалению, я не получил ответа... Я думаю, что пока не могу использовать этот пакет для параллельной работы. Я даже посмотрел исходный код функции, но для этого я, видимо, слишком новичок :/   -  person Jonny    schedule 30.05.2016
comment
@AchimZeileis Думаю, теперь я нашел ошибку. Функция as.party.C5.0 вызывает другую неэкспортированную функцию model.frame.C5.0. В этом методе вызывается базовая функция eval(), которая использует неправильную среду (в которой объект d в данном случае больше не находится). Решение состоит в том, чтобы вставить env = parent.frame(2), поскольку среда должна быть вторым родительским фреймом. Есть ли у меня возможность отредактировать исходный код, чтобы он использовал исправление ошибки, если сопровождающий этого не увидит? Я уже пробовал это   -  person Jonny    schedule 30.05.2016
comment
да, это очевидная проблема (если вы раньше работали с формулами/терминами/модельными рамками), но решение parent.frame(2), вероятно, не самое лучшее или самое надежное решение. Я думаю, что было бы предпочтительнее сохранить terms (как я писал выше), которые сохраняют информацию об окружении. По крайней мере, это то, что я попытался бы реализовать, если бы был сопровождающим. Если Max не отвечает на ваши запросы, самое простое решение — загрузить .tar.gz пакета из CRAN, изменить исходные коды, заново собрать и установить пакет на свой компьютер.   -  person Achim Zeileis    schedule 30.05.2016
comment
о, я вижу, теперь ваш первый комментарий также имеет для меня еще больше смысла ;-) извините, это мой первый раз, когда я углубляюсь в пакет. На данный момент я сделал, как вы предложили. Я скачал исходник, изменил его (но только на решение parent.frame(2)) и снова установил измененный пакет. Кажется, он работает с функцией as.party() и функцией fitted. Но все же исправление ошибки сопровождающим было бы здорово!   -  person Jonny    schedule 30.05.2016


Ответы (1)


Это ошибка. Мы следуем совету Ахима и используем объект terms, за исключением случаев, когда мы понимаем регистр неверно .

Попробуйте установить с github через

devtools::install_github("topepo/C5.0/pkg/C50")

Ваши примеры работают на этой версии.

person topepo    schedule 31.05.2016