海南建设网站,营销软文范文,外包工好还是派遣工好,深圳设计周一、说明 贝叶斯推理#xff0c;也就是变分概率模型估计#xff0c;属于高级概率学模型#xff0c;极有学习价值#xff1b;一般来说#xff0c;配合实际活动学习可能更直观#xff0c;而pyro是pytorch的概率工具#xff0c;不同于以往的概率工具#xff0c;只是集中于…
一、说明 贝叶斯推理也就是变分概率模型估计属于高级概率学模型极有学习价值一般来说配合实际活动学习可能更直观而pyro是pytorch的概率工具不同于以往的概率工具只是集中于统计工具而pyro具备贝叶斯推断的全套设计因此跟着pyro学习会更有前景因此建议读者重视pyro的存在这就是本文的意义所在。
二、火焰兵简介
2.1 火焰是个啥 概率是在不确定性下进行推理的数学就像微积分是对变化率进行推理的数学一样。它为理解现代机器学习和人工智能的大部分内容提供了一个统一的理论框架用概率语言构建的模型可以捕获复杂的推理知道他们不知道什么并在没有监督的情况下揭示数据结构。 直接指定概率模型可能很麻烦而且实现它们也很容易出错。概率编程语言 (PPL) 通过将概率与编程语言的表示能力相结合来解决这些问题。概率程序是普通确定性计算和代表数据生成过程的随机采样值的混合。 通过观察概率程序的结果我们可以描述一个推理问题大致翻译为“如果这个随机选择具有某个观察值那么什么一定是真的” PPL 明确强制分离已经隐含在概率数学中的模型规范、要回答的查询和计算答案的算法之间的关注点分离。 Pyro 是一种基于 Python 和 PyTorch 构建的概率编程语言。Pyro 程序只是 Python 程序而其主要推理技术是随机变分推理它将抽象的概率计算转换为 PyTorch 中通过随机梯度下降解决的具体优化问题使概率方法适用于以前难以处理的模型和数据集大小。 在本教程中我们将简要介绍概率机器学习和 Pyro 概率编程的基本概念。我们通过涉及线性回归的示例数据分析问题来实现这一点线性回归是机器学习中最常见和基本的任务之一。我们将了解如何使用 Pyro 的建模语言和推理算法将不确定性纳入回归系数的估计中。
2.2 在python中安装pyro
2.2.1 安装的步骤分三个过程
1步骤1pip3 install pyro-ppl 2步骤2git clone https://github.com/pyro-ppl/pyro.git3步骤3cd pyro
pip install .[extras]
2.2.2 安装过程的错误和改出 执行git clone https://github.com/pyro-ppl/pyro.git 可能的错误是 OpenSSL SSL_read: Connection was reset, errno 10054
此为验证过程出错可以从下列操作改出
git config --global http.sslVerify false 执行git clone https://github.com/pyro-ppl/pyro.git 可能的错误是 Failed to connect to github.com port 443: Timed out
此为验证过程出错可以从下列操作改出
git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy http://127.0.0.1:1080git config --global --unset http.proxy
git config --global --unset https.proxy 执行git clone https://github.com/pyro-ppl/pyro.git 执行成功等待下载完成完成下载后安装
3步骤3cd pyro
pip install .[extras] 三、大纲提示 介绍 大纲 设置 背景概率机器学习 背景概率模型 背景推理、学习和评估 示例地理和国民收入 Pyro 中的模型 模型示例最大似然线性回归 背景pyro.sample 原语 背景pyro.param 原语 背景pyro.plate 原语 示例从最大似然回归到贝叶斯回归 Pyro 中的推理 背景变分推理 背景“引导”程序作为灵活的近似后验 示例Pyro 中贝叶斯线性回归的平均场变分近似 背景估计和优化证据下限 (ELBO) 示例通过随机变分推理 (SVI) 的贝叶斯回归 Pyro 中的模型评估 背景使用后验预测检查的贝叶斯模型评估 示例Pyro 中的后验预测不确定性 示例使用满秩指南重新审视贝叶斯回归 下一步
四、设置
让我们首先导入我们需要的模块。
%reset -s -f
import logging
import osimport torch
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as pltimport pyro[43]:smoke_test (CI in os.environ)
assert pyro.__version__.startswith(1.8.6)pyro.enable_validation(True)
pyro.set_rng_seed(1)
logging.basicConfig(format%(message)s, levellogging.INFO)# Set matplotlib settings
%matplotlib inline
plt.style.use(default)五、背景概率机器学习 大多数数据分析问题可以理解为对三个基本高级问题的阐述 在观察任何数据之前我们对问题了解多少 根据我们的先验知识我们可以从数据中得出什么结论 这些结论有意义吗 在数据科学和机器学习的概率或贝叶斯方法中我们用概率分布的数学运算形式化这些方法。
5.1 背景概率模型 首先我们以概率模型或随机变量集合的联合概率分布的形式表达我们所知道的关于问题中的变量以及它们之间的关系的所有信息。模型有观察结果x和潜在随机变量z以及参数θ。它通常具有以下形式的联合密度函数 潜在变量的分布 在这个公式中称为先验以及给定潜在变量的观察变量的分布 称为可能性。 我们通常要求各种条件概率分布 组成一个模型 具有以下属性通常由Pyro和PyTorch Distributions中可用的分布满足 我们可以有效地从每个 我们可以有效地计算逐点概率密度 对于参数是可微分的θ 概率模型通常以用于可视化和通信的标准图形表示法来描述总结如下尽管 Pyro 中可以表示没有固定图形结构的模型。在具有大量重复的模型中使用板表示法很方便之所以这么称呼是因为它以图形方式显示为围绕变量的矩形“板”以指示内部随机变量的多个独立副本。 5.2 背景推理、学习和评估 一旦我们指定了一个模型贝叶斯规则就会告诉我们如何使用它来执行推理或者通过计算后验分布从数据中得出有关潜在变量的结论z: 为了检查建模和推理的结果我们想知道模型与观测数据的拟合程度如何x我们可以用证据或边际可能性来量化 还可以对新数据进行预测我们可以使用后验预测分布来进行预测 最后通常需要学习参数θ我们的模型来自观察到的数据x我们可以通过最大化边际似然来实现 5.3 示例地理和国民收入 下示例改编自 Richard McElreath 撰写的优秀著作《统计反思》的第 7章鼓励读者阅读该书以获取对贝叶斯数据分析更广泛实践的简单介绍所有章节的 Pyro 代码均可用。 我们想探讨一个国家的地形异质性通过地形崎岖指数数据集中的变量崎岖度衡量与其人均 GDP 之间的关系。特别是原论文 《崎岖非洲恶劣地理的祝福》 的作者指出地形崎岖或恶劣的地理与非洲以外地区较差的经济表现有关但崎岖的地形却产生了相反的影响关于非洲国家的收入。 让我们看一下数据并研究这种关系。我们将重点关注数据集中的三个特征 rugged量化地形坚固性指数 cont_africa指定国家是否在非洲 rgdppc_20002000年人均实际GDP
[44]:DATA_URL https://d2hg8soec8ck9v.cloudfront.net/datasets/rugged_data.csv
data pd.read_csv(DATA_URL, encodingISO-8859-1)
df data[[cont_africa, rugged, rgdppc_2000]]响应变量 GDP 高度偏斜因此我们将在继续之前对其进行对数转换。
[45]:df df[np.isfinite(df.rgdppc_2000)]
df[rgdppc_2000] np.log(df[rgdppc_2000])然后我们将此数据帧后面的 Numpy 数组转换为torch.Tensor用于使用 PyTorch 和 Pyro 进行分析的数组。
[46]:train torch.tensor(df.values, dtypetorch.float)
is_cont_africa, ruggedness, log_gdp train[:, 0], train[:, 1], train[:, 2]数据可视化表明坚固性和 GDP 之间确实可能存在某种关系但需要进一步分析来证实这一关系。我们将了解如何在 Pyro 中通过贝叶斯线性回归来做到这一点。
[47]:fig, ax plt.subplots(nrows1, ncols2, figsize(12, 6), shareyTrue)
african_nations df[df[cont_africa] 1]
non_african_nations df[df[cont_africa] 0]
sns.scatterplot(xnon_african_nations[rugged],ynon_african_nations[rgdppc_2000],axax[0])
ax[0].set(xlabelTerrain Ruggedness Index,ylabellog GDP (2000),titleNon African Nations)
sns.scatterplot(xafrican_nations[rugged],yafrican_nations[rgdppc_2000],axax[1])
ax[1].set(xlabelTerrain Ruggedness Index,ylabellog GDP (2000),titleAfrican Nations);六、Pyro 中的模型 Pyro 中的概率模型被指定为 Python 函数这些函数使用特殊的原始函数从潜在变量生成观察到的数据这些函数的行为可以通过 Pyro 的内部结构根据正在执行的高级计算进行更改。model(*args, **kwargs) 具体来说不同的数学部分model()通过映射进行编码 潜在随机变量 见网页 观察到的随机变量 带有obs关键字参数的pyro.sample 可学习参数 盘子⟺ Pyro.plate上下文管理器
我们在下面的第一个线性回归 Pyro 模型的背景下详细研究了这些组件中的每一个。
6.1 模型示例最大似然线性回归
如果我们写出线性回归预测器的公式作为 Python 表达式我们得到以下结果
mean a b_a * is_cont_africa b_r * ruggedness b_ar * is_cont_africa * ruggedness为了将其构建为数据集的完整概率模型我们需要制作回归系数和可学习的参数并在预测平均值周围添加观察噪声。 我们可以使用上面介绍的 Pyro 原语来表达这一点并使用Pyro.render_model()可视化结果模型
[48]:import pyro.distributions as dist
import pyro.distributions.constraints as constraintsdef simple_model(is_cont_africa, ruggedness, log_gdpNone):a pyro.param(a, lambda: torch.randn(()))b_a pyro.param(bA, lambda: torch.randn(()))b_r pyro.param(bR, lambda: torch.randn(()))b_ar pyro.param(bAR, lambda: torch.randn(()))sigma pyro.param(sigma, lambda: torch.ones(()), constraintconstraints.positive)mean a b_a * is_cont_africa b_r * ruggedness b_ar * is_cont_africa * ruggednesswith pyro.plate(data, len(ruggedness)):return pyro.sample(obs, dist.Normal(mean, sigma), obslog_gdp)pyro.render_model(simple_model, model_args(is_cont_africa, ruggedness, log_gdp), render_distributionsTrue)[48]:上图未显示模型参数a、b_a、b_r、b_ar和sigma。我们可以设置render_paramsTrue渲染模型参数。
[49]:pyro.render_model(simple_model, model_args(is_cont_africa, ruggedness, log_gdp), render_distributionsTrue, render_paramsTrue)[49]:该参数将显示对参数的约束。例如是一个标准差应该是非负的。因此其约束表示为“sigmarender_distributions Truesigma∈大于lower_bound0.0”。 学习 的参数simple_model将构成最大似然估计并产生回归系数的点估计。然而在这个例子中我们的数据可视化表明我们不应该对回归系数的任何单个值过于自信。相比之下完全贝叶斯方法将产生对不同可能参数值以及模型预测的不确定性估计。 在制作线性模型的贝叶斯版本之前让我们停下来仔细看看第一段 Pyro 代码。
6.2 背景pyro.sample原始
Pyro 中的概率程序是围绕原始概率分布的样本构建的标记为pyro.sample
def sample(name: str,fn: pyro.distributions.Distribution,*,obs: typing.Optional[torch.Tensor] None,infer: typing.Optional[dict] None
) - torch.Tensor:...在我们上面的模型中simple_model该行
return pyro.sample(obs, dist.Normal(mean, sigma), obslog_gdp)可以表示潜在变量或观察变量具体取决于是否simple_model给定log_gdp值。当log_gdp未提供并且obs是潜在的时它相当于pyro.plate通过假设 暂时忽略上下文调用分发的底层方法len(ruggedness) 1.sample
return dist.Normal(mean, sigma).sample()这种解释是偶尔将 Pyro 程序引用为随机函数的背后原因随机函数是 Pyro 的一些旧文档中使用的一个相当晦涩的术语。 当simple_model给出一个log_gdp参数并被obs观察时该pyro.sample语句
return pyro.sample(obs, dist.Normal(mean, sigma), obslog_gdp)总会返回log_gdp
return log_gdp但是请注意当观察到任何样本语句时模型中每个其他样本语句的累积效应都会按照贝叶斯规则发生变化Pyro推理算法的工作是“向后运行程序”并为pyro.sample模型中的所有语句分配数学上一致的值。 此时要问的一个合理的问题是为什么pyro.sample和 其他基元必须有名称。用户和 Pyro 内部人员利用名称来区分模型、观察和推理算法的规范这是概率编程语言的一个关键卖点。要查看这样的示例我们可以查看高阶原始的pyro.condition它解决了针对单个 Pyro 模型编写许多查询的问题
def condition(model: Callable[..., T],data: Dict[str, torch.Tensor]
) - Callable[..., T]:...pyro.condition接受一个模型和一个可能是空的字典将名称映射到观察值并将每个观察传递到pyro.sample其名称指示的语句。在我们的示例中simple_model我们可以删除log_gdp作为参数并用更简单的接口替换它。
def simpler_model(is_cont_africa, ruggedness): ...conditioned_model pyro.condition(simpler_model, data{obs: log_gdp})其中conditioned_model相当于
conditioned_model functools.partial(simple_model, log_gdplog_gdp)6.3 背景pyro.param原始 我们模型中使用的下一个原语是pyro.param它是一个用于读取和写入 Pyro 的键值参数存储的前端
def param(name: str,init: Optional[Union[torch.Tensor, Callable[..., torch.Tensor]]] None,*,constraint: torch.distributions.constraints.Constraint constraints.real
) - torch.Tensor:...就像pyro.sample,pyro.param总是以名称作为第一个参数来调用。第一次pyro.param使用特定名称调用时它将第二个参数指定的初始值存储init在参数存储中然后返回该值。之后当使用该名称调用它时它会从参数存储中返回值而不管任何其他参数如何。参数初始化后不再需要指定init检索其值例如 pyro.param(a)。 第二个参数init可以是一个torch.Tensor或一个不带参数并返回张量的函数。第二种形式很有用因为它避免了重复构造仅在模型第一次运行时使用的初始值。 与 PyTorch 不同torch.nn.ParameterPyro 中的参数可以显式约束为各种子集这是一个重要的特征因为许多基本概率分布的参数具有受限的域。例如分布scale的参数Normal必须为正。pyro.param,的可选第三个参数constraint是 初始化参数时存储的 torch.distributions.constraints.Constraint对象每次更新后都会重新应用约束。Pyro 附带了大量预定义的约束。 pyro.param值在模型调用中持续存在除非参数存储由优化算法更新或通过pyro.clear_param_store()清除。与 不同的是pyro.samplepyro.param可以在模型中多次调用相同的名称每个具有相同名称的调用都会返回相同的值。全局参数存储本身可以通过调用 pyro.get_param_store()来访问。 在我们上面的模型中simple_model语句
a pyro.param(a, lambda: torch.randn(()))在概念上与下面的代码类似但具有一些附加的跟踪、序列化和约束管理功能。
simple_param_store {}
...
def simple_model():a_init lambda: torch.randn(())a simple_param_store[a] if a in simple_param_store else a_init()...虽然本介绍性教程用pyro.param于参数管理但 Pyro 还通过pyro.nn.PyroModule与 PyTorch 熟悉的API, torch.nn.Module兼容。
6.4 背景pyro.plate原始 pyro.plate是 Pyro 的板表示法的形式编码广泛用于概率机器学习以简化具有大量条件独立且同分布随机变量的模型的可视化和分析。
def plate(name: str,size: int,*,dim: Optional[int] None,**other_kwargs
) - contextlib.AbstractContextManager:...从概念上讲pyro.plate语句相当于for循环。在 中simple_model我们可以替换这些行
with pyro.plate(data, len(ruggedness)):return pyro.sample(obs, dist.Normal(mean, sigma), obslog_gdp)使用 Pythonfor循环
result torch.empty_like(ruggedness)
for i in range(len(ruggedness)):result[i] pyro.sample(fobs_{i}, dist.Normal(mean, sigma), obslog_gdp[i] if log_gdp is not None else None)
return result当重复变量的数量len(ruggedness)在本例中很大时使用 Python 循环会非常慢。由于循环中的每次迭代都独立于其他迭代因此pyro.plate使用 PyTorch 的数组广播在单个向量化操作中并行执行迭代如以下等效向量化代码所示
mean mean.unsqueeze(-1).expand((len(ruggedness),))
sigma sigma.unsqueeze(-1).expand((len(ruggedness),))
return pyro.sample(obs, dist.Normal(mean, sigma), obslog_gdp)实际上在编写 Pyro 程序时pyro.plate作为矢量化工具最有用。然而正如SVI 教程第 2 部分中所述它对于管理数据子采样以及作为某些变量是独立的推断算法的信号也很有用。
6.5 示例从最大似然回归到贝叶斯回归 为了建立贝叶斯线性回归模型我们需要指定参数的先验分布 和 此处扩展为标量b_a、b_r和b_ar。这些是概率分布代表我们在观察有关合理值的任何数据之前的信念α和β。我们还将添加一个随机比例参数σ控制观察噪声。 在 Pyro 中表达线性回归的贝叶斯模型非常直观我们只需将每个语句替换pyro.param为pyro.sample配备有描述每个参数的先验信念的Pyro Distribution 对象的语句。 对于常数项α我们使用具有较大标准差的正态先验来表明我们相对缺乏关于基线 GDP 的先验知识。对于其他回归系数我们使用标准正态先验以 0 为中心来表示我们缺乏关于协变量与 GDP 之间的关系是正还是负的先验知识。对于观测噪声σ我们使用低于 0 的平坦先验因为该值必须为正才能成为有效的标准差。
[50]:def model(is_cont_africa, ruggedness, log_gdpNone):a pyro.sample(a, dist.Normal(0., 10.))b_a pyro.sample(bA, dist.Normal(0., 1.))b_r pyro.sample(bR, dist.Normal(0., 1.))b_ar pyro.sample(bAR, dist.Normal(0., 1.))sigma pyro.sample(sigma, dist.Uniform(0., 10.))mean a b_a * is_cont_africa b_r * ruggedness b_ar * is_cont_africa * ruggednesswith pyro.plate(data, len(ruggedness)):return pyro.sample(obs, dist.Normal(mean, sigma), obslog_gdp)pyro.render_model(model, model_args(is_cont_africa, ruggedness, log_gdp), render_distributionsTrue)[50]: