Использование функции bnlearn cpquery в цикле

Я пытаюсь использовать bnlearn пакет для расчета условных вероятностей, и я столкнулся с проблемой, когда Функция "cpquery" используется внутри цикла. Я создал пример, показанный ниже, используя данные, включенные в пакет. При использовании функции cpquery в цикле переменная, созданная в цикле ("evi" в примере), не распознается функцией. Я получаю сообщение об ошибке:

Error in parse(text = evi) : object 'evi' not found

Этапы создания "evi" основаны на примерах, предоставленных автором.

Любая помощь, которую вы могли бы оказать, была бы здоровой. Я отчаянно пытаюсь найти способ применить функцию cpquery для большого количества наблюдений.

library(bnlearn)
data(learning.test)
fitted = bn.fit(hc(learning.test), learning.test)

bn.function <- function(network, evidence_data) {
  a <- NULL
  b <- nrow(evidence_data)
  for (i in 1:b) {
    evi <- paste("(", names(evidence_data), "=='",
               sapply(evidence_data[i,], as.character), "')",
               sep = "", collapse = " & ")
    a[i] <- cpquery(network, (C=='c'), eval(parse(text=evi)))
  }
  return(a)
}

test <- bn.function(fitted, learning.test)

Заранее спасибо!


person H2O_Research    schedule 08.10.2013    source источник
comment
Я связался с автором пакета bnlearn, и оказалось, что ошибка, которую я получаю, связана с проблемой области действия функции cpquery. Это становится очевидным, когда я могу заставить функцию cpquery работать должным образом в цикле for, созданном вне определяемой пользователем функции, но с ошибкой, когда тот же цикл for используется внутри пользовательской функции.   -  person H2O_Research    schedule 11.10.2013
comment
У меня была аналогичная проблема с cpquery в циклах, и быстрый обходной путь, который сработал для меня, заключался в том, чтобы включить строку evi <<- evi перед вызовом cpquery. Это определяет переменную в глобальной среде.   -  person Austin    schedule 31.05.2018
comment
Я думаю, ваша проблема была решена здесь: stackoverflow.com/questions /44676501/   -  person drastega    schedule 27.12.2019


Ответы (2)


Я не знаю, связано ли это с исправлением ошибки или просто потому, что я попробовал другой подход - в любом случае цикл работает, если вы итеративно создаете список доказательств вне функции cpquery.

Пример итерации по списку с именемvideData со всеми положительными свидетельствами:

for(i in names(evidenceData)){
  loopEvidenceList <- list()
  loopEvidenceList[[i]] <- "TRUE"
  a =cpquery(fitted = bayesNet, event = queryNode == "TRUE", 
             evidence = loopEvidenceList, method = "lw", n = 100000)
  print(a)
  }

В зависимости от того, как доступны ваши доказательства, вам может потребоваться более сложная подготовка «loopEvidenceList», но как только вы это подготовите, все будет работать нормально.

person locom    schedule 07.05.2018

Чтобы избежать проблемы с областью действия, вы можете отложить вызов eval и сделать это внутри функции cpquery. Если вы напрямую передадите evi (символьную переменную) в cpquery, а затем проанализируете ее внутри определения, цепочка сред будет смещена, и cpquery получит доступ к evi.

Вы можете использовать m.cpquery <- edit(cpquery) для создания собственной версии функции и вставить в ее начало следующую строку:

evidence = parse(text = evidence)

а затем сохраните новую функцию.

Таким образом, заголовок m.cpquery будет выглядеть так:

> m.cpquery
function (fitted, event, evidence, cluster = NULL, method = "ls", 
    ..., debug = FALSE) 
{
    evidence = parse(text = evidence)
    check.fit(fitted)
    check.logical(debug)
...

Теперь вы можете использовать m.cpquery в своей собственной функции, как и раньше, за исключением того, что мы передадим ей переменную простого символа:

a[i] <- m.cpquery(network, (C=='c'), evi)

Обратите внимание, что в первой строке m.cpquery мы проанализировали только символьную переменную свидетельства и не вызывали для нее eval. cpquery — это внешний интерфейс для conditional.probability.query (см. здесь) и мы полагаемся на последующий вызов conditional.probability.query eval.

Я должен сказать, что это довольно уродливый обходной путь. И это работает, только если вы используете логическую выборку (method='ls'). Но если вы хотите использовать взвешивание правдоподобия, функция check.mutilated.evidence вызовет ошибку. Я не проверял, приведет ли вставка выражения eval до его вызова к хаосу последующих ошибок, ведущих к аду.

person koohyar    schedule 02.10.2016