通过 Monte Carlo 马尔可夫链移植到 PyMC3 的简单贝叶斯网络

Simple Bayesian Network via Monte Carlo Markov Chain ported to PyMC3

我在文件 pymc3_rain_sprinkler_grass_simple_bayesian_network.py.

中的 GitHub 上移植了 Simple Bayesian Network via Monte Carlo Markov Chain from PyMC2 to PyMC3 and it works.
The result can be found in the following gist 的示例

我想通过提供证据来扩展原始示例,例如草是湿的然后让 PyMC3 给我回答 "given grass is wet, what is the probability that it has rained?".

这样的问题

生成的轨迹似乎是 "constant",例如它不再有随机性的元素。看看要点中的 pymc3_rain_sprinkler_grass_simple_bayesian_network_with_evidence.py 并执行 df.drop_duplicates() 看看我的意思。

我做错了什么?

我设法解决了我的问题。要点是将 testval 设置为 "true" 而不是 "false"。将步长方法从 Metropolis 更改为 BinaryGibbsMetropolis,改善了这种情况。

完整的解决方案供参考。我也更新了要点。

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)