Path: blob/master/site/zh-cn/probability/examples/Modeling_with_JointDistribution.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
Licensed under the Apache License, Version 2.0 (the "License");
使用联合分布的贝叶斯建模
JointDistributionSequential
是新引入的分布式类,使用户能够快速构建贝叶斯模型原型。它支持将多个分布链接在一起,并使用 lambda 函数来引入依赖项。这旨在构建包括许多常用模型在内的中小型贝叶斯模型,如 GLM、混合效应模型、混合模型等。它可以实现贝叶斯工作流的所有必要功能:先验预测采样,它可以插入另一个更大的贝叶斯图模型或神经网络。在此 Colab 中,我们将展示一些示例以说明如何使用 JointDistributionSequential
来实现您的日常贝叶斯工作流
依赖项和前提条件
加快速度!
在我们深入探究之前,请确保我们在此演示中使用 GPU。
为此,请选择“Runtime”->“Change runtime type”->“Hardware accelerator”->“GPU”。
以下代码段将验证我们是否可以使用 GPU。
注:如果由于某种原因无法使用 GPU,则此 Colab 仍然有效。(训练将花费更长时间。)
JointDistribution
注:当您只有一个简单的模型时,此分布类非常实用。“简单”是指链式计算图;尽管该方式在技术上适用于单一节点最多为 255(因为 Python 函数最多可以包含这么多参数)的任何 PGM。
基本理念是让用户指定一个可生成 tfp.Distribution
实例的 callable
列表,逐一用于 PGM 中的每个顶点。callable
最多可具有与其列表内索引同等数量的参数。(为方便用户,参数将以与创建时相反的顺序进行传递。)在内部,我们会通过将每个先前 RV 的值传递给每个可调用对象来“遍历计算图”。这样,我们便实现了[概率的链式法则](https://en.wikipedia.org/wiki/Chain_rule_(probability)#More_than_two_random_variables): ParseError: KaTeX parse error: Expected '}', got '&' at position 31: …d_i^d p(x_i|x*{&̲lt;i})。
这一理念非常简单,即便为 Python 代码。大意如下:
您可以从 JointDistributionSequential
的文档字符串中找到更多信息,但大意是要传递一个分布列表来初始化类,如果列表中的某些分布取决于另一个上游分布/变量的输出,则只需使用 lambda 函数来对其进行封装。现在,让我们看看它的实际运行效果!
(稳健)线性回归
出自 PyMC3 文档 GLM:使用离群点检测的稳健回归
传统 OLS 模型
现在,让我们建立一个线性模型,一个简单的截距 + 斜率回归问题:
然后,您可以检查模型的计算图以查看依赖关系。请注意,x
保留为最后一个节点的名称,您无法确定它是 JointDistributionSequential 模型中的 lambda 参数。
从模型中采样非常简单:
…它提供了 tf.Tensor 列表。您可以立即将其插入 log_prob 函数以计算模型的 log_prob:
嗯,这里有些不太对:我们应该得到一个标量 log_prob!实际上,我们可以通过调用 .log_prob_parts
来进一步检查是否存在问题,它给出了图模型中每个节点的 log_prob
:
…结果是最后一个节点并未沿 i.i.d. 维度/轴求 reduce_sum!当我们求和时,前两个变量因此被错误地广播。
这里的技巧是使用 tfd.Independent
重新解释批次形状(以便轴的其余部分被正确缩减):
现在,让我们检查模型的最后一个节点/分布,您可以看到事件形状现已正确解释。请注意,可能需要一些反复试验才能使 reinterpreted_batch_ndims
正确,但您始终可以轻松打印分布或采样的张量以复查形状!
其他 JointDistribution*
API
最大似然估计
现在,我们可以进行推断了!您可以使用优化器来找到最大似然估计。
批处理版本模型和马尔科夫链蒙特卡洛法
在贝叶斯推断中,我们通常希望使用马尔科夫链蒙特卡洛样本,因为当样本来自后验时,我们可以将其插入到任何函数中来计算期望值。然而,马尔科夫链蒙特卡洛 API 要求我们编写批处理友好型模型,我们可以通过调用 sample([...])
来检查实际上不可“批处理”的模型
此例相对简单,因为我们的模型中只有一个线性函数,扩展形状应该奏效:
我们可以再次对 log_prob_parts 进行采样和评估以进行一些检查:
一些附注:
我们希望使用批处理版本模型,因为它对于多链马尔科夫链蒙特卡洛法来说速度最快。如果您无法将模型重写为批处理版本(例如 ODE 模型),您可以使用
tf.map_fn
映射 log_prob 函数以达到相同的效果。现在,由于我们具有先验标量,因此
mdl_ols_batch.sample()
可能不起作用,原因是我们不能执行scalar_tensor[:, None]
。这里的解决方案是通过封装tfd.Sample(..., sample_shape=1)
将标量张量扩展到 1 阶。将模型编写为函数是一种很好的做法,这样您就可以更轻松地更改超参数等设置。
使用 No-U-Turn 采样器的马尔科夫链蒙特卡洛法
Student-T 方法
请注意,我们从现在开始将始终使用批处理版本模型
前向采样(先验预测采样)
最大似然估计
马尔科夫链蒙特卡洛法
分层部分池化
前向采样(先验预测采样)
再次注意,如果您不使用 Independent,最终会得到具有错误 batch_shape 的 log_prob。
最大似然估计
tfp.optimizer
的一个非常惊人的功能是,您可以并行优化 k 批起点并指定 stopping_condition
kwarg:您可以将其设置为 tfp.optimizer.converged_all
以查看它们是否全部找到相同的最小值,或设置为 tfp.optimizer.converged_any
以快速找到局部解。
LBFGS 没有收敛。
马尔科夫链蒙特卡洛法
对于具有复杂转换的模型,以函数式风格实现会使编写和测试更加方便。此外,它也能够使以编程方式生成以(小批量)输入数据为条件的 log_prob 函数变得更加方便:
变分推断
JointDistribution*
的一项非常强大的功能是您可以轻松地为变分推断生成逼近。例如,要执行平均场自动微分变分推断,您只需检查计算图并将所有未观察到的分布替换为正态分布。
平均场自动微分变分推断
您还可以使用 tensorflow_probability/python/experimental/vi 中的实验性功能来构建变分逼近,它们与下面使用的逻辑基本相同(即使用 JointDistribution 来构建逼近),但使用的是原始空间而非无界空间内的逼近输出。
满秩自动微分变分推断
对于满秩自动微分变分推断,我们想逼近多元高斯分布后验。
贝塔-伯努利混合模型
一种混合模型,其中多个审查者使用未知(真实)潜在标签标记某些条目。