Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynamicBayesianNetwork limitations #1340

Open
nihil21 opened this issue Oct 5, 2020 · 6 comments · May be fixed by #1471
Open

DynamicBayesianNetwork limitations #1340

nihil21 opened this issue Oct 5, 2020 · 6 comments · May be fixed by #1471

Comments

@nihil21
Copy link
Contributor

nihil21 commented Oct 5, 2020

Subject of the issue

From what I've understood, in pgmpy it's possible to define DynamicBayesianNetwork's edges only in the first time slice (as in #714); so, to define a DBN as the following:

immagine

I would need to add the edges in the first time slice, like this:

immagine

However, by doing so I would create a loop, and thus pgmpy throws an error.

In my opinion, forcing to define edges in the first time slice is very limiting: functional loops over time are a desired property of DBN, but in this way we lose such property.

@ankurankan
Copy link
Member

@nihil21 Yes, I agree with you. DBNs haven't been my main focus as you can see with the number of bugs. But if you would like to contribute something like this, you are most welcome and I think it would be very interesting and useful.

@FelipeGiro
Copy link
Contributor

@ankurankan I can work on this. Could you assign me?

@FelipeGiro
Copy link
Contributor

FelipeGiro commented Sep 9, 2021

The code.

A DBN with functional loop:

import numpy as np
from scipy.special import softmax
from pgmpy.models import DynamicBayesianNetwork
from pgmpy.inference import DBNInference
from pgmpy.factors.discrete import TabularCPD

edges=[
( ('A', 0) , ('A', 1) ),
( ('A', 0) , ('B', 1) ),
( ('B', 0) , ('B', 1) ),
( ('B', 0) , ('C', 1) ),
( ('C', 0) , ('A', 1) ),
( ('C', 0) , ('C', 1) )
]

bnet=DynamicBayesianNetwork(edges)#, latents=set('L'))

bnet_cpds = []
bnet_cpds.append(
    TabularCPD(('A', 0), 2, softmax(np.ones((2,1)), axis=0)))
bnet_cpds.append(
    TabularCPD(('B', 0), 2, softmax(np.ones((2,1)), axis=0)))
bnet_cpds.append(
    TabularCPD(('C', 0), 2, softmax(np.ones((2,1)), axis=0)))
bnet_cpds.append(
    TabularCPD(('A', 1), 2, softmax(np.ones((2,4)), axis=0), evidence=[('A', 0), ('C', 0)], evidence_card=[2,2]))
bnet_cpds.append(
    TabularCPD(('B', 1), 2, softmax(np.ones((2,4)), axis=0), evidence=[('A', 0), ('B', 0)], evidence_card=[2,2]))
bnet_cpds.append(
    TabularCPD(('C', 1), 2, softmax(np.ones((2,4)), axis=0), evidence=[('B', 0), ('C', 0)], evidence_card=[2,2]))

bnet.add_cpds(*bnet_cpds)
ie=DBNInference(bnet)

The error:

Traceback (most recent call last):
  File "c:/Developments/test.py", line 34, in <module>
    ie=DBNInference(bnet)
  File "c:\developments\pgmpy\pgmpy\inference\dbn_inference.py", line 59, in __init__      
    self._initialize_structures()
  File "c:\developments\pgmpy\pgmpy\inference\base.py", line 105, in _initialize_structures
    self.start_bayesian_model.add_cpds(*self.model.get_cpds(time_slice=0))
  File "c:\developments\pgmpy\pgmpy\models\BayesianNetwork.py", line 258, in add_cpds
    raise ValueError("CPD defined on variable not in the model", cpd)
ValueError: ('CPD defined on variable not in the model', <TabularCPD representing P(('A', 0):2) at 0x16013c1aac8>)

Issue

self.nodes() returns NodeView(()) in:

if set(cpd.scope()) - set(cpd.scope()).intersection(set(self.nodes())):
raise ValueError("CPD defined on variable not in the model", cpd)

So, whatever the value for cpd.scope(), will always raise an error.

Questions

@ankurankan

  1. Where exactly self.nodes() is defined? I think the problem is related to the nodes creation, but I cannot see where it is generated.
  2. Why if I run bnet.nodes() right after initalizating the DBN, all nodes will be there?

NodeView((<DynamicNode(A, 0) at 0x1639a532b48>, <DynamicNode(A, 1) at 0x1639a532d08>, <DynamicNode(B, 1) at 0x1639a532b08>, <DynamicNode(B, 0) at 0x1639a532d88>, <DynamicNode(C, 1) at 0x1639a532e08>, <DynamicNode(C, 0) at 0x1639a532e48>))

@ankurankan
Copy link
Member

@FelipeGiro Are you using the latest dev branch? Because I am not able to reproduce the error. Your code snippet works fine on my machine.

The nodes method btw is from networkx.DiGraph.

@FelipeGiro
Copy link
Contributor

My mistake, I forgot one line of code: ie=DBNInference(bnet). I just updated my previous comment.

I did not notice BayesianNetwork is called by DBNInference instead of DynamicBayesianNetwork.

@ankurankan
Copy link
Member

@FelipeGiro I looked at this issue and I think if we replace the Bayesian model creation before inference here: https://github.com/pgmpy/pgmpy/blob/dev/pgmpy/inference/base.py#L104 with calls to DynamicBayesianNetwork.get_const_bn, then it should work fine. What do you think?

@FelipeGiro FelipeGiro linked a pull request Oct 5, 2021 that will close this issue
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants