Sample code (Python preferred) for Dynamic Bayesian Network
Sample code (Python preferred) for Dynamic Bayesian Network
Hello,
I have searched for sample code showing how to create a DBN and do some inferences with it (preferably but not necessarily in Python), and I
have found nothing. Do you know of any samples you can share with me?
Regards,
Rafael
I have searched for sample code showing how to create a DBN and do some inferences with it (preferably but not necessarily in Python), and I
have found nothing. Do you know of any samples you can share with me?
Regards,
Rafael
-
- Site Admin
- Posts: 61
- Joined: Mon Nov 06, 2017 6:41 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
I'll try to explain PySmile DBN usage based on GeNIe documentation: https://support.bayesfusion.com/docs/Ge ... ngdbn.html
1. Create CPT nodes, ex.
2. Set node temporal types
Default type is CONTEMPORAL, so you don't have to change Location node type.
3. Create arcs 4. Set node definitions
5. Update beliefs and check if everything is ok.
1. Create CPT nodes, ex.
Code: Select all
net.add_node("Location")
net.add_node("Rain")
net.add_node("Umbrella")
Code: Select all
net.set_node_temporal_type("Rain", pysmile.NodeTemporalType.PLATE)
net.set_node_temporal_type("Umbrella", pysmile.NodeTemporalType.PLATE)
3. Create arcs 4. Set node definitions
Code: Select all
net.set_node_definition("Location", [0.5, 0.5])
net.set_node_definition("Rain", [0.9,0.1,0.2,0.8])
net.set_node_temporal_definition("Rain", [0.7,0.3,0.3,0.7,0.001,0.999,0.01,0.99])
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Thank you! However, I got this error message:
I fixed it this way
Then I got the following error:
So I guessed order was the number of time steps in the temporal relation, so I set it to 1, and the network definition is working.
I let you know about the inference, but I have a question. Is it necessary to have some initial condition or a contemporal node.
Code: Select all
TypeError: add_node(): incompatible function arguments. The following argument types are supported:
1. (self: pysmile.Network, node_type: int, node_id: unicode) -> int
2. (self: pysmile.Network, node_type: int) -> int
3. (self: pysmile.Network) -> int
Code: Select all
handle = net.add_node()
net.set_node_temporal_type(handle, pysmile.NodeTemporalType.PLATE)
net.set_node_id(handle,id)
net.set_node_name(handle, name)
Code: Select all
TypeError: set_node_temporal_definition(): incompatible function arguments. The following argument types are supported:
1. (self: pysmile.Network, node_handle: int, order: int, definition: List[float]) -> None
2. (self: pysmile.Network, node_id: unicode, order: int, definition: List[float]) -> None
I let you know about the inference, but I have a question. Is it necessary to have some initial condition or a contemporal node.
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Well, net.update_beliefs() seems to go well, but then I have problems printing the posteriors:
Please, find attached the code and the resulting network.
Code: Select all
Network written to colaborar_din.xdsl
Starting inferencing...
Posteriors with no evidence set:
P(Colaborar_G = Bajo) = 0.5
P(Colaborar_G = Medio) = 0.5
P(Colaborar_G = Alto) = 0.0
Traceback (most recent call last):
File "modest_dynamic.py", line 180, in <module>
InferenceOnNetwork(cn.get_network())
File "modest_dynamic.py", line 146, in __init__
self.print_all_posteriors(net)
File "modest_dynamic.py", line 167, in print_all_posteriors
self.print_posteriors(net, h)
File "modest_dynamic.py", line 160, in print_posteriors
value = net.get_outcome_id(node_handle, i)
RuntimeError: basic_string::_M_construct null not valid
- Attachments
-
- modest_dynamic.txt
- (5.48 KiB) Downloaded 755 times
-
- colaborar_din.xdsl
- (10.69 KiB) Downloaded 748 times
-
- Site Admin
- Posts: 61
- Joined: Mon Nov 06, 2017 6:41 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Code: Select all
def print_posteriors(self, net, node_handle):
node_id = net.get_node_id(node_handle)
if net.is_evidence(node_handle):
print(node_id + " has evidence set (" +
net.get_outcome_id(node_handle,
net.get_evidence(node_handle)) + ")")
else :
posteriors = net.get_node_value(node_handle)
for i in range(0, len(posteriors)):
value = net.get_outcome_id(node_handle, i)
p = posteriors[i]
print("P(" + node_id + " = " + value + ") = " + str(p))
Code: Select all
value = net.get_outcome_id(node_handle, i)
Code: Select all
value = net.get_outcome_id(node_handle, i%net.get_outcome_count(node_handle))
Re: Sample code (Python preferred) for Dynamic Bayesian Network
I did the changes and it started working! Then I discovered all variables in the initial state of the net have the same probability distribution (0.5, 0.5, 0), so I initialized the top variable (CG) adding the following to my code
Then I found that there was not propagation on the initial state of the net, so I added a full definition for the initial state of the net,
and everything is fine now!
Some questions:
Code: Select all
t = self.stream_table(cpd.flatDist(3))
net.set_node_definition(cg, t)
Code: Select all
t = self.stream_table(cpd.incsub(2))
net.set_node_definition(pg, t)
net.set_node_definition(ag, t)
t = self.stream_table(cpd.genesp())
net.set_node_definition(ce, t)
t = self.stream_table(cpd.join(cpd.genesp(),cpd.incsub(2)))
net.set_node_definition(pe, t)
net.set_node_definition(ae, t)
t = self.stream_table(cpd.compevi())
net.set_node_definition(ec, t)
net.set_node_definition(ep, t)
net.set_node_definition(ea, t)
Some questions:
- Why beliefs initialization goes through 10 steps in time?
- How do I add evidences along time? (I have a guess on this one, but I ask it just in case I am wrong)
- Is there a way to recover the net at time t (all nodes probability distributions at time t)?
-
- Site Admin
- Posts: 61
- Joined: Mon Nov 06, 2017 6:41 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
It depends on Slice (Step) Count variable. You can change it by calling ex. net.set_slice_count(4) (four steps). Remember to update beliefs.Why beliefs initialization goes through 10 steps in time?
net.set_temporal_evidence(handle, slice, outcome)How do I add evidences along time? (I have a guess on this one, but I ask it just in case I am wrong)
If you want to get network definition, you should call get_node_temporal_definition method for each node. If your intention is to read the node values, use get_node_value method and read values corresponding to searched 't' value.Is there a way to recover the net at time t (all nodes probability distributions at time t)?
I hope it helps,
Piotr
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Dear Piotr,
Thank you very much for your help. I can get the 16 time slices I wanted. However, I guess I am doing something wrong because the behaviour is not as expected. Given the temporal evidence
Competencia Tiempo Nivel
'e_proponer' 1 0
'e_aportar' 2 0
'e_proponer' 4 1
'e_aportar' 5 1
'e_colaborar' 7 1
'e_proponer' 10 2
'e_aportar' 11 1
'e_colaborar' 14 1
I get the following results with SMILE:
They are too flat, as if the network is almost no reacting to the evidence. Consider, for example, the same evidence on PGMPY
These results are more credible.
So, I am attaching the code, hoping you have time to have a look at it.
Thank you very much for your help. I can get the 16 time slices I wanted. However, I guess I am doing something wrong because the behaviour is not as expected. Given the temporal evidence
Competencia Tiempo Nivel
'e_proponer' 1 0
'e_aportar' 2 0
'e_proponer' 4 1
'e_aportar' 5 1
'e_colaborar' 7 1
'e_proponer' 10 2
'e_aportar' 11 1
'e_colaborar' 14 1
I get the following results with SMILE:
They are too flat, as if the network is almost no reacting to the evidence. Consider, for example, the same evidence on PGMPY
These results are more credible.
So, I am attaching the code, hoping you have time to have a look at it.
- Attachments
-
- modest_dynamic.py.txt
- (6.93 KiB) Downloaded 750 times
-
- Site Admin
- Posts: 61
- Joined: Mon Nov 06, 2017 6:41 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Code: Select all
def print_posteriors(net, node_handle):
node_id = net.get_node_id(node_handle)
if net.is_evidence(node_handle):
print(node_id + " has evidence set (" +
net.get_outcome_id(node_handle,
net.get_evidence(node_handle)) + ")")
else :
posteriors = net.get_node_value(node_handle)
n = net.get_outcome_count(node_handle)
for i in range(0, len(posteriors)):
value = value = net.get_outcome_id(node_handle, i%n)
p = posteriors[i]
print("P(" + node_id + " = " + value + ") = " + str(p))
Could you tell me, how to reproduce these charts?
Genie shows, that node values change in time (Aportar_E at image).
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Thank you! I would fix my is_evidence call. The charts are created using a spreadsheets (attached). And yes, the probabilities move, but too little. Consider the first pair or evidences on value 0 for e_proponer and e_aportar, they should have moved the probabilities much more than they are, as it happens with pgmpy. Unless in the SMILE case the temporal conditional are too strong.
- Attachments
-
- bajoMedio16-smile.zip
- (45.44 KiB) Downloaded 784 times
-
- bajoMedio16-pgmpy.zip
- (33.33 KiB) Downloaded 745 times
-
- Site Admin
- Posts: 61
- Joined: Mon Nov 06, 2017 6:41 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
We have noticed that something is not quite right with network definition. You probably have not set nodes definition for t=0 (ex. Proponer_E)
It should be set with method set_node_definition (not like other slices - set_node_temporal_definition). Also notice, that in SMILE 'time' variable starts with 0 - if pgmpy starts with 1, you can get different results.Re: Sample code (Python preferred) for Dynamic Bayesian Network
I have the opportunity to install Genie on a Windows machine, and I get a nice picture of my map:
I have followed the manual and revised the tables, and everything seems to be fine, bot the t = 0 definitions,
as the temporal ones,
Then I add the evidence, and update the beliefs.
with
Yet, the model seems to be insensitive to to evidence. So I am wondering whether what I miss are initial conditions of some kind, or there is something deep wrong in the model.
I have followed the manual and revised the tables, and everything seems to be fine, bot the t = 0 definitions,
Code: Select all
net.add_arc(cg, pg)
net.add_arc(cg, ag)
net.add_arc(cg, ce)
net.add_arc(pg, pe)
net.add_arc(ce, pe)
net.add_arc(ag, ae)
net.add_arc(ce, ae)
net.add_arc(ce, ec)
net.add_arc(pe, ep)
net.add_arc(ae, ea)
# Non temporal conditionals. Time 0
t = self.stream_table(cpd.flatDist(3))
net.set_node_definition(cg,t)
t = self.stream_table(cpd.incsub(2))
net.set_node_definition(pg, t)
net.set_node_definition(ag, t)
t = self.stream_table(cpd.genesp())
net.set_node_definition(ce, t)
t = self.stream_table(cpd.join(cpd.genesp(),cpd.incsub(2)))
net.set_node_definition(pe, t)
net.set_node_definition(ae, t)
t = self.stream_table(cpd.compevi())
net.set_node_definition(ec, t)
net.set_node_definition(ep, t)
net.set_node_definition(ea, t)
Code: Select all
# Temporal arcs
net.add_temporal_arc(cg,cg,1)
net.add_temporal_arc(pg,pg,1)
net.add_temporal_arc(ag,ag,1)
net.add_temporal_arc(ce,ce,1)
net.add_temporal_arc(pe,pe,1)
net.add_temporal_arc(ae,ae,1)
# Non temporal conditionals. Time 0
t = self.stream_table(cpd.flatDist(3))
net.set_node_definition(cg,t)
t = self.stream_table(cpd.incsub(2))
net.set_node_definition(pg, t)
net.set_node_definition(ag, t)
t = self.stream_table(cpd.genesp())
net.set_node_definition(ce, t)
t = self.stream_table(cpd.join(cpd.genesp(),cpd.incsub(2)))
net.set_node_definition(pe, t)
net.set_node_definition(ae, t)
t = self.stream_table(cpd.compevi())
net.set_node_definition(ec, t)
net.set_node_definition(ep, t)
net.set_node_definition(ea, t)
# Conditionals that include temporal relations
tpp = cpd.paspre()
t = self.stream_table(tpp)
net.set_node_temporal_definition(cg, 1, t)
t = self.stream_table(cpd.join(cpd.incsub(2),tpp))
net.set_node_temporal_definition(pg, 1, t)
net.set_node_temporal_definition(ag, 1, t)
t = self.stream_table(cpd.join(cpd.genesp(),tpp))
net.set_node_temporal_definition(ce, 1, t)
t = self.stream_table(cpd.join(cpd.genesp(),cpd.incsub(2),tpp))
net.set_node_temporal_definition(pe, 1, t)
net.set_node_temporal_definition(ae, 1, t)
Code: Select all
self.change_evidence_and_update(net, 'e_proponer', 1, 'Bajo')
self.change_evidence_and_update(net, 'e_aportar', 2, 'Bajo')
self.change_evidence_and_update(net, 'e_proponer', 4, 'Medio')
self.change_evidence_and_update(net, 'e_aportar', 5, 'Medio')
self.change_evidence_and_update(net, 'e_colaborar', 7, 'Medio')
self.change_evidence_and_update(net, 'e_proponer', 10, 'Alto')
self.change_evidence_and_update(net, 'e_aportar', 11, 'Medio')
self.change_evidence_and_update(net, 'e_colaborar', 14, 'Medio')
net.set_slice_count(17)
net.update_beliefs()
Code: Select all
def change_evidence_and_update(self, net, node_id, n_time, outcome_id):
if outcome_id is not None:
net.set_temporal_evidence(node_id, n_time, outcome_id)
else:
net.clear_temporal_evidence(node_id, n_time)
- Attachments
-
- colaborar_din.xdsl
- (11.99 KiB) Downloaded 778 times
-
- Site Admin
- Posts: 61
- Joined: Mon Nov 06, 2017 6:41 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Code: Select all
self.change_evidence_and_update(net, 'e_proponer', 1, 'Bajo')
self.change_evidence_and_update(net, 'e_aportar', 2, 'Bajo')
self.change_evidence_and_update(net, 'e_proponer', 4, 'Medio')
self.change_evidence_and_update(net, 'e_aportar', 5, 'Medio')
self.change_evidence_and_update(net, 'e_colaborar', 7, 'Medio')
self.change_evidence_and_update(net, 'e_proponer', 10, 'Alto')
self.change_evidence_and_update(net, 'e_aportar', 11, 'Medio')
self.change_evidence_and_update(net, 'e_colaborar', 14, 'Medio')
net.set_slice_count(17)
net.update_beliefs()
eg. e_colaboral values: If you need more informations about DBNs, you can check GeNIe documentation: https://support.bayesfusion.com/docs/Ge ... ction.html
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Well, it looks like there is some differences in understanding what a DBN is. I was thinking on something that evolves in time; i.e. conditional probabilities in nodes in slice t+1 depend only on conditional probabilities in nodes in the same slice and slice t. So evidences for e_proponer = 0 and e_aportar = 0 in slices 1 and 2 would make conditional probabilities for nodes 'Proponer_E' and 'Aportar_E' to "move" towards 0. But it seems to me now that what the system tries to do is to consider all the slices and evidences all together, as a large static BN, and considering all evidence together.
Is that the case?
Is that the case?
-
- Site Admin
- Posts: 1422
- Joined: Mon Nov 26, 2007 5:51 pm
Re: Sample code (Python preferred) for Dynamic Bayesian Network
Your temporal arcs have order 1, therefore your CPTs in t+1 are conditioned on nodes in t+1 and t. However, the calculated posterior probabilities depend on the entire unrolled network and the evidence set. To calculate the posteriors, SMILE unrolls the network into a static BN containing the specified number of slices, performs inference and copies the results into original DBN. You can use the 'Unroll' command in GeNIe to visualize the process.conditional probabilities in nodes in slice t+1 depend only on conditional probabilities in nodes in the same slice and slice t.
For more info, see Using GeNIe/Dynamic Bayesian Networks chapter in GeNIe manual.