Skip to content

Instantly share code, notes, and snippets.

@rtbs-dev
Last active March 24, 2023 16:43
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 16 You must be signed in to fork a gist
  • Save rtbs-dev/1349864212b25cce91dbe5e336d794b4 to your computer and use it in GitHub Desktop.
Save rtbs-dev/1349864212b25cce91dbe5e336d794b4 to your computer and use it in GitHub Desktop.
Bayesian Network Models in PyMC3 and NetworkX
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@rtbs-dev
Copy link
Author

Updated to use tabular look-up for pre-defined categorical composition nodes. Removed need for theano.tensor.switch() in most cases, using a shared numpy slice on the table instead. Runs much faster.

Still uses T.switch() for splitting the continuous node C3

@rtbs-dev
Copy link
Author

Added example of programmatically instantiating the PyMC3 random variable objects using NetworkX dicts. In theory, one could now "loop-over" an existing network and build up a pymc3 model to do inference.

@madHatter106
Copy link

This is really cool. Thanks!

@Nilavro
Copy link

Nilavro commented Sep 16, 2018

How do you make a query ? For example P(C3 |C2 = 12)

@dynaryu
Copy link

dynaryu commented Nov 13, 2018

I've got the following error message when I tried the Networkx with PyMC3:


TypeError Traceback (most recent call last)
in
8 BN.node['D2']['dist_obj'] = pm.Categorical('D2',p=BN.node['D2']['prob'])
9
---> 10 BN.node['C1']['dist_obj'] = pm.Normal('C1', mu=10+4*gpm(BN,'C1'),
11 tau = (1./2)*2)
12 BN.node['C2']['dist_obj'] = pm.Normal('C2', mu=6+2
(gpm(BN,'C2'))**2,

in gpm(BN, node, num)
1 # utily to quickly access the parent nodes' pymc3 objects
2 def gpm(BN, node, num=0):
----> 3 return BN.node[BN.predecessors(node)[num]]['dist_obj']
4
5 with pm.Model() as mod2:

TypeError: 'dict_keyiterator' object is not subscriptable

I'm currently using networkx 2.2, pymc3 3.5, and python 3.5 on OS X

@Fangwq
Copy link

Fangwq commented Jan 2, 2019

I got the following error message:

Traceback (most recent call last):
File "./pmml_test.py", line 126, in
BN.node['C1']['dist_obj'] = pm.Normal('C1', mu=10+4*gpm(BN,'C1'),tau = (1./2)**2)
File "./pmml_test.py", line 118, in gpm
return BN.node[BN.predecessors(node)[num]]['dist_obj']
TypeError: 'dictionary-keyiterator' object has no attribute 'getitem'

I'm currently using networkx 2.2, pymc3 3.5, and python 2.7 on OS X. Can you help me?

@DanielaLaura
Copy link

I got the following error message:

Traceback (most recent call last):
File "./pmml_test.py", line 126, in
BN.node['C1']['dist_obj'] = pm.Normal('C1', mu=10+4*gpm(BN,'C1'),tau = (1./2)**2)
File "./pmml_test.py", line 118, in gpm
return BN.node[BN.predecessors(node)[num]]['dist_obj']
TypeError: 'dictionary-keyiterator' object has no attribute 'getitem'

I'm currently using networkx 2.2, pymc3 3.5, and python 2.7 on OS X. Can you help me?

Here, he is using network 1.x. Here is the Migration guide :https://networkx.github.io/documentation/stable/release/migration_guide_from_1.x_to_2.0.html

In :
"# utily to quickly access the parent nodes' pymc3 objects
def gpm(BN, node, num=0):
return BN.node[BN.predecessors(node)[num]]['dist_obj'] "
you have to change BN.predecessors(node) to list(BN.predecessors(node)).

That is why you might get that keyiterator error.

Edit: aslo, you might want to change BN.node to BN.nodes
Hope it helps!

@DanielaLaura
Copy link

I've got the following error message when I tried the Networkx with PyMC3:

TypeError Traceback (most recent call last)
in
8 BN.node['D2']['dist_obj'] = pm.Categorical('D2',p=BN.node['D2']['prob'])
9
---> 10 BN.node['C1']['dist_obj'] = pm.Normal('C1', mu=10+4gpm(BN,'C1'),
11 tau = (1./2)
2) 12 BN.node['C2']['dist_obj'] = pm.Normal('C2', mu=6+2(gpm(BN,'C2'))**2,

in gpm(BN, node, num)
1 # utily to quickly access the parent nodes' pymc3 objects
2 def gpm(BN, node, num=0):
----> 3 return BN.node[BN.predecessors(node)[num]]['dist_obj']
4
5 with pm.Model() as mod2:

TypeError: 'dict_keyiterator' object is not subscriptable

I'm currently using networkx 2.2, pymc3 3.5, and python 3.5 on OS X

Here, he is using network 1.x. Here is the Migration guide :https://networkx.github.io/documentation/stable/release/migration_guide_from_1.x_to_2.0.html

In :
"# utily to quickly access the parent nodes' pymc3 objects
def gpm(BN, node, num=0):
return BN.node[BN.predecessors(node)[num]]['dist_obj'] "
you have to change BN.predecessors(node) to list(BN.predecessors(node)).

That is why you might get that keyiterator error.

Edit: aslo, you might want to change BN.node to BN.nodes
Hope it helps!

@tomkovna
Copy link

tomkovna commented Jan 7, 2019

How do you make a query such as: P(C1_a<C1<C1_b | C3_a<C3<C3_b, D4 = 1)?

@13charliebrown
Copy link

I am getting the following error:

Traceback (most recent call last):

File "", line 30, in
BN.edge['C3']['D4']['bin']], observed=BN.node['D4']['observe'])

File "C:\Users\Andrea\Anaconda3\lib\site-packages\theano\tensor\var.py", line 544, in getitem
theano.tensor.subtensor.Subtensor.convert(arg)

File "C:\Users\Andrea\Anaconda3\lib\site-packages\theano\tensor\subtensor.py", line 354, in convert
raise TypeError("Expected an integer")

TypeError: Expected an integer

Any help, please? Thanks!

@Fangwq
Copy link

Fangwq commented Mar 7, 2019

I get the same error with pymc3 3.6 and python3.

Traceback (most recent call last):
File "pmml_test.py", line 147, in
[gpm(BN,'D4', num=1),BN.adj['C3']['D4']['bin']], observed=BN.node['D4']['observe'])
File "/Users/fangwq/Library/Python/3.6/lib/python/site-packages/theano/tensor/var.py", line 544, in getitem
theano.tensor.subtensor.Subtensor.convert(arg)
File "/Users/fangwq/Library/Python/3.6/lib/python/site-packages/theano/tensor/subtensor.py", line 354, in convert
raise TypeError("Expected an integer")
TypeError: Expected an integer

Any help, please? Thanks!

@NelisW
Copy link

NelisW commented Jul 1, 2019

Thanks to all above!
I have about four hours experience in pymc3, so the above comments are much appreciated.

Using networkx 2.3 and pyMC3 3.7, cpu on Windows.
Fixed the dict_keyiterator problem.

    32     BN.edge['C3']['D4']['bin'] = T.switch(T.lt(gpm(BN,'D4'),9), 0, 
---> 33                                           T.switch(T.gt(gpm(BN,'D4'), 9) & T.lt(gpm(BN,'D4'),11), 1, 2))

AttributeError: 'DiGraph' object has no attribute 'edge'

When print(BN.__dict__) I see no edge attribute.
The edges seem to be embedded in _adj, _pred and _succ.

BN = nx.DiGraph()
BN.add_node('D1', dtype='Discrete', prob=d1_prob, pos=(2, 4))
BN.add_node('D2', dtype='Discrete', prob=d2_prob, pos=(4, 4))
BN.add_node('C1', dtype='Continuous', mu=c1_mu, sd=c1_sd, pos=(1,3))
BN.add_edge('D1', 'C1')
print(BN.__dict__)
-----------------------------------------------
{
'graph_attr_dict_factory': <class 'dict'>, 'node_dict_factory': <class 'dict'>, 
'node_attr_dict_factory': <class 'dict'>, 'adjlist_outer_dict_factory': <class 'dict'>, 
'adjlist_inner_dict_factory': <class 'dict'>, 'edge_attr_dict_factory': <class 'dict'>, 
'graph': {}, 
'_node': {
  'D1': {'dtype': 'Discrete', 'prob': array([0.3, 0.7]), 'pos': (2, 4)}, 
  'D2': {'dtype': 'Discrete', 'prob': array([0.6, 0.3, 0.1]), 'pos': (4, 4)}, 
  'C1': {'dtype': 'Continuous', 'mu': array([10, 14]), 'sd': array([2, 2]), 'pos': (1, 3)}
  }, 
'_adj': {'D1': {'C1': {}}, 'D2': {}, 'C1': {}},
'_pred': {'D1': {}, 'D2': {}, 'C1': {'D1': {}}}, 
'_succ': {'D1': {'C1': {}}, 'D2': {}, 'C1': {}}
}

D1 is a predecessor for C1.
C1 is a successor for D1.
But C1 is also adjacent to D1?

My bigger issue is what to do with the error on line 32/33 above.

I have no idea how to handle this. Any help will be appreciated!

@rtbs-dev
Copy link
Author

rtbs-dev commented Jul 1, 2019

Wow, I had no idea there were comments here! Thanks to all for checking out the example. For those of you with issues/ideas (especially networkx v2 problems), check out the repository that automates a lot of the underlying mechanical/boilerplate code in this example. This notebook was really just a proof-of-concept for that repository.

I haven't gone back to the code for a while, but if there's interest I would be happy to update things to newer pymc3 features. Please see if your above issues persist in the more mature repository. Thanks!

@NelisW
Copy link

NelisW commented Jul 1, 2019 via email

@rtbs-dev
Copy link
Author

rtbs-dev commented Jul 1, 2019

@NelisW certainly, and like I said, feel free to open an issue if something works unexpectedly on that repo (as I said, it's been a while).

@eHonnef
Copy link

eHonnef commented Nov 22, 2019

If you are having issues with BN.edges['C3']['D4']['bin'], substitute for BN.edges['C3','D4']['bin'].

As described in the migration guide mentioned before

G.edge have been removed in favor of using G.nodes[n] and G.edges[u, v]

@rezaaskary
Copy link

Do you have any example for dynamic BN simulated on PYMC3?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment