我正在尝试用几个离散的随机变量和条件概率来构建贝叶斯网络的最简单的例子(科勒的书中的“学生网络”,参见1)
虽然有点笨拙,但我还是设法用pymc3构建了这个网络。特别是,在pymc3中创建CPD并不是那么简单,请参阅以下代码片段:
import pymc3 as pm
...
with pm.Model() as basic_model:
# parameters for categorical are indexed as [0, 1, 2, ...]
difficulty = pm.Categorical(name='difficulty', p=[0.6, 0.4])
intelligence = pm.Categorical(name='intelligence', p=[0.7, 0.3])
grade = pm.Categorical(name='grade',
p=pm.math.switch(
theano.tensor.eq(intelligence, 0),
pm.math.switch(
theano.tensor.eq(difficulty, 0),
[0.3, 0.4, 0.3], # I=0, D=0
[0.05, 0.25, 0.7] # I=0, D=1
),
pm.math.switch(
theano.tensor.eq(difficulty, 0),
[0.9, 0.08, 0.02], # I=1, D=0
[0.5, 0.3, 0.2] # I=1, D=1
)
)
)
letter = pm.Categorical(name='letter', p=pm.math.switch(
...
但是我不知道如何使用10个低概率(版本:tfp-nightly==0.7.0.dev20190517
,tf-nightly-2.0-preview==2.0.0.dev20190517
)来构建这个网络
对于无条件的二进制变量,可以使用分类分布,例如
from tensorflow_probability import distributions as tfd
from tensorflow_probability import edward2 as ed
difficulty = ed.RandomVariable(
tfd.Categorical(
probs=[0.6, 0.4],
name='difficulty'
)
)
但是如何构建CPDs呢?
在tensorflow-probability中有几个类/方法可能是相关的(在tensorflow_probability/python/distributions/deterministic.py
或不推荐使用的ConditionalDistribution
中),但文档相当稀疏(需要深入理解tfp)。
-更新后的问题
Chris的回答是一个很好的起点。然而,即使对于一个非常简单的双变量模型,事情仍然有点不清楚。
这样做效果很好:
jdn = tfd.JointDistributionNamed(dict(
dist_x=tfd.Categorical([0.2, 0.8], validate_args=True),
dist_y=lambda dist_x: tfd.Bernoulli(probs=tf.gather([0.1, 0.9], indices=dist_x), validate_args=True)
))
print(jdn.sample(10))
但是这个失败了
jdn = tfd.JointDistributionNamed(dict(
dist_x=tfd.Categorical([0.2, 0.8], validate_args=True),
dist_y=lambda dist_x: tfd.Categorical(probs=tf.gather_nd([[0.1, 0.9], [0.5, 0.5]], indices=[dist_x]))
))
print(jdn.sample(10))
(我试图在第二个例子中显式地对分类进行建模,只是为了学习)
--更新:已解决
显然,最后一个示例错误地使用了tf.gather_nd
而不是tf.gather
,因为我们只想根据dist_x
内容选择第一行或第二行。下面的代码现在可以工作了:
jdn = tfd.JointDistributionNamed(dict(
dist_x=tfd.Categorical([0.2, 0.8], validate_args=True),
dist_y=lambda dist_x: tfd.Categorical(probs=tf.gather([[0.1, 0.9], [0.5, 0.5]], indices=[dist_x]))
))
print(jdn.sample(10))
发布于 2019-05-24 03:37:19
这件事的棘手之处在于--就像矢量化编程中的几乎所有东西一样--处理形状,这大概也是它在PyMC中比预期更微妙的原因。
在TF/TFP中,解决这个问题的(IMO)最好的方法是使用一个新的TFP JointDistribution{Sequential,Named,Coroutine}
类。这些可以让你自然地表示分层的PGM模型,然后从它们中采样,评估日志问题等。
我迅速准备了一个colab笔记本,演示了所有三种方法,用于完整的学生网络:https://colab.research.google.com/drive/1D2VZ3OE6tp5pHTsnOAf_7nZZZ74GTeex
请注意,tf.gather和tf.gather_nd的关键用法是管理各种二进制和分类切换的矢量化。
看一看,如果你有任何问题,请告诉我!
https://stackoverflow.com/questions/56271275
复制相似问题