I'm trying to create my own bayesian network programme to model a very simple court ruling scenario using pomegranate, very similar to the monty hall problem which is well documented as an example of bayesian networks with pomegranate. I have made the node testifies (whether the witness testifies that the defendant is guilty or not) dependent on the nodes reliable (if the witness is reliable or not) and guilty (whether the defendant has committed the crime or not). However when I try to assign a certain value or belief to the nodes, in order to see how the conditional probabilities of the other nodes change, using beliefs = predict_proba() it seems that no values are being assigned to these nodes as the array beliefs simply returns the full probability distribution of each variable as if every variable in the system is still unknown. Is there anything missing from my code which could fix this?
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
This returns
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)
When it should just return
array(['T','F',
{
"class" : "Distribution",
"dtype" : "str",
"name" : "DiscreteDistribution",
"parameters" : [
{
"T" : 0.5,
"F" : 0.5
}
],
"frozen" : false
}], dtype=object)
Good question, this is indeed surprising behavior. A little poking and I discovered there are two things going on here.
yields this:
Answer
That leads us to one of two ways to get what you want. Your way with Caps:
or a list of lists, where we have to include
None
for nodes to infer:both of which yield:
That's not the [.5, .5] you expected, but it is the correct answer from your CPT.
Extra
You will get [.5, .5] if you flip the inputs:
And if you can do inverse reasoning, if you know how to read the node order: