2

我正在尝试创建自己的贝叶斯网络程序,以使用石榴对非常简单的法院裁决场景进行建模,这与 monty hall 问题非常相似,该问题已被充分记录为石榴贝叶斯网络的示例。我已经使节点作证(证人是否证明被告有罪)取决于节点是否可靠(证人是否可靠)和有罪(被告是否犯罪)。但是,当我尝试为节点分配某个值或信念时,为了查看其他节点的条件概率如何变化,使用信念 = 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)
4

1 回答 1

0

好问题,这确实是令人惊讶的行为。稍微戳了一下,我发现这里发生了两件事。

  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)]
于 2020-12-16T20:18:12.127 回答