简体   繁体   中英

Simple Bayesian Network via Monte Carlo Markov Chain ported to PyMC3

I was porting the example of a Simple Bayesian Network via Monte Carlo Markov Chain from PyMC2 to PyMC3 and it works.
The result can be found in the following gist on GitHub in the file pymc3_rain_sprinkler_grass_simple_bayesian_network.py.

I wanted to extend the original example by providing evidence, eg that the grass is wet and then let PyMC3 give me the answer for questions like "given grass is wet, what is the probability that it has rained?".

It seems that the resulting trace is "constant", eg there is no element of randomness in it any more. Have a look at pymc3_rain_sprinkler_grass_simple_bayesian_network_with_evidence.py in the gist and execute the df.drop_duplicates() to see what I mean.

What am I doing wrong?

I managed to solve my problem. The main point was to set testval to "true" rather than "false". It improved the situation to change the step method from Metropolis to BinaryGibbsMetropolis.

For reference here is the complete solution. I also updated the gist.

import numpy as np
import pandas as pd
import pymc3 as pm

niter = 10000  # 10000
tune = 5000  # 5000

model = pm.Model()

with model:
    tv = [1]
    rain = pm.Bernoulli('rain', 0.2, shape=1, testval=tv)
    sprinkler_p = pm.Deterministic('sprinkler_p', pm.math.switch(rain, 0.01, 0.40))
    sprinkler = pm.Bernoulli('sprinkler', sprinkler_p, shape=1, testval=tv)
    grass_wet_p = pm.Deterministic('grass_wet_p', pm.math.switch(rain, pm.math.switch(sprinkler, 0.99, 0.80), pm.math.switch(sprinkler, 0.90, 0.0)))
    grass_wet = pm.Bernoulli('grass_wet', grass_wet_p, observed=np.array([1]), shape=1)

    trace = pm.sample(20000, step=[pm.BinaryGibbsMetropolis([rain, sprinkler])], tune=tune, random_seed=124)

# pm.traceplot(trace)

dictionary = {
              'Rain': [1 if ii[0] else 0 for ii in trace['rain'].tolist() ],
              'Sprinkler': [1 if ii[0] else 0 for ii in trace['sprinkler'].tolist() ],
              'Sprinkler Probability': [ii[0] for ii in trace['sprinkler_p'].tolist()],
              'Grass Wet Probability': [ii[0] for ii in trace['grass_wet_p'].tolist()],
              }
df = pd.DataFrame(dictionary)

p_rain = df[(df['Rain'] == 1)].shape[0] / df.shape[0]
print(p_rain)

p_sprinkler = df[(df['Sprinkler'] == 1)].shape[0] / df.shape[0]
print(p_sprinkler)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM