Как присвоить убеждение/значение узлу в байесовской сети, используя predict_proba() из граната

Я пытаюсь создать свою собственную байесовскую сетевую программу для моделирования очень простого сценария судебного решения с использованием граната, очень похожего на проблему Монти Холла, которая хорошо задокументирована как пример байесовских сетей с гранатом. Я сделал узел свидетельских показаний (свидетельствует ли свидетель о виновности подсудимого или нет) зависимыми от узлов надежных (надежный свидетель или нет) и виновных (совершил подсудимый преступление или нет). Однако, когда я пытаюсь присвоить узлам определенное значение или убеждение, чтобы увидеть, как меняются условные вероятности других узлов, используя убеждения = предсказать_проба(), кажется, что этим узлам не присваиваются значения в качестве убеждений массива. просто возвращает полное распределение вероятностей каждой переменной, как будто каждая переменная в системе все еще неизвестна. Что-то отсутствует в моем коде, что могло бы это исправить?

from pomegranate import *
import math
import pomegranate as pg
reliable = DiscreteDistribution({'T':3.0/4.0, 'F':1.0/4.0})
guilty = DiscreteDistribution({'T':1.0/2.0, 'F':1.0/2.0})
testifies = ConditionalProbabilityTable([['T','T','T',1.0],
                                         ['T','T','F',0.0],
                                         ['T','F','T',0.0],
                                         ['T','F','F',1.0],
                                         ['F','T','T',0.5],
                                         ['F','T','F',0.5],
                                         ['F','F','T',0.5],
                                         ['F','F','F',0.5]],[reliable,guilty])


s1 = State(reliable,name="Reliable")
s2 = State(guilty,name="Guilty")
s3 = State(testifies,name="Testifies")

network = BayesianNetwork("Court Ruling")
network.add_states(s1,s2,s3)

network.add_edge(s1,s3)
network.add_edge(s2,s3)

network.bake()


beliefs = network.predict_proba({'reliable':'T','guilty':'F'})
beliefs

Это возвращает

array([ {
"class" : "Distribution",
"dtype" : "str",
"name" : "DiscreteDistribution",
"parameters" : [
    {
        "T" : 0.7499999999999998,
        "F" : 0.2500000000000002
    }
],
"frozen" : false
},
   {
"class" : "Distribution",
"dtype" : "str",
"name" : "DiscreteDistribution",
"parameters" : [
    {
        "T" : 0.5,
        "F" : 0.5
    }
],
"frozen" : false
},
   {
"class" : "Distribution",
"dtype" : "str",
"name" : "DiscreteDistribution",
"parameters" : [
    {
        "T" : 0.5,
        "F" : 0.5
    }
],
"frozen" : false
}], dtype=object)

Когда он должен просто вернуться

array(['T','F',
   {
"class" : "Distribution",
"dtype" : "str",
"name" : "DiscreteDistribution",
"parameters" : [
    {
        "T" : 0.5,
        "F" : 0.5
    }
],
"frozen" : false
}], dtype=object)

person Conor Joseph Walsh    schedule 13.12.2020    source источник


Ответы (1)


Хороший вопрос, это действительно удивительное поведение. Немного поковырявшись, я обнаружил, что здесь происходят две вещи.

  1. Вам нужно отправить список dict. Это полное игнорирование того, что вы отправляете, и просто предоставление маргинала для всей сети. На эту чушь ответ один и тот же:
network.predict_proba({'bunting':'red','frog':'green'})
  1. Добавление списка показывает, что он чувствителен к регистру, например:
network.predict_proba([{'reliable':'T','guilty':'F'}])

дает это:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
...
ValueError: Model does not contain a state named 'reliable'

Отвечать

Это приводит нас к одному из двух способов получить то, что вы хотите. Ваш путь с Caps:

network.predict_proba([{'Reliable':'T','Guilty':'F'}])

или список списков, где мы должны включить None для выводов узлов:

network.predict_proba([['T','F',None]])

оба из которых дают:

[array(['T', 'F',
        {
     "class" : "Distribution",
     "dtype" : "str",
     "name" : "DiscreteDistribution",
     "parameters" : [
         {
             "F" : 1.0,
             "T" : 0.0
         }
     ],
     "frozen" : false
 }], dtype=object)]

Это не тот [.5, .5], который вы ожидали, но это правильный ответ вашего CPT.

Дополнительный

Вы получите [.5, .5], если перевернете входы:

network.predict_proba([{'Reliable':'F','Guilty':'T'}])

[array(['F', 'T',
        {
     "class" : "Distribution",
     "dtype" : "str",
     "name" : "DiscreteDistribution",
     "parameters" : [
         {
             "F" : 0.5,
             "T" : 0.5
         }
     ],
     "frozen" : false
 }], dtype=object)]

И если вы можете делать обратные рассуждения, если вы знаете, как читать порядок узлов:

network.predict_proba([{'Testifies':'T'}])
[array([{
     "class" : "Distribution",
     "dtype" : "str",
     "name" : "DiscreteDistribution",
     "parameters" : [
         {
             "T" : 0.7499999999999999,
             "F" : 0.25000000000000017
         }
     ],
     "frozen" : false
 },
        {
     "class" : "Distribution",
     "dtype" : "str",
     "name" : "DiscreteDistribution",
     "parameters" : [
         {
             "T" : 0.8749999999999999,
             "F" : 0.12500000000000022
         }
     ],
     "frozen" : false
 },
        'T'], dtype=object)]
person ctwardy    schedule 16.12.2020