SVI¶
- class SVI(model, guide, optim, loss, loss_and_grads=None, num_samples=0, num_steps=0, **kwargs)[source]¶
基础类:
pyro.infer.abstract_infer.TracePosterior
- Parameters
model – 模型(包含Pyro原语的可调用对象)
指南 – 指南(包含Pyro原语的可调用对象)
optim (PyroOptim) – 一个用于PyTorch优化器的包装器
loss (pyro.infer.elbo.ELBO) –
ELBO
子类的实例。 Pyro 提供了三种内置的损失函数:Trace_ELBO
,TraceGraph_ELBO
, 和TraceEnum_ELBO
. 请参阅ELBO
文档以了解如何实现自定义损失函数。num_samples – (已弃用) 用于蒙特卡罗后验近似的样本数量
num_steps – (已弃用) 在
run()
中执行的优化步骤数
Pyro中用于随机变分推断的统一接口。最常用的损失函数是
loss=Trace_ELBO()
。有关讨论,请参阅教程SVI Part I。- run(*args, **kwargs)[source]¶
警告
此方法已弃用,并将在未来的版本中移除。 对于推理,请直接使用
step()
,对于预测, 请使用Predictive
类。
ELBO¶
- class ELBOModule(model: torch.nn.modules.module.Module, guide: torch.nn.modules.module.Module, elbo: pyro.infer.elbo.ELBO)[source]¶
- class ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[source]¶
基础类:
object
ELBO
是通过优化证据下界进行随机变分推断的顶级接口。大多数用户不会直接与这个基类
ELBO
交互; 相反,他们会创建派生类的实例:Trace_ELBO
,TraceGraph_ELBO
, 或TraceEnum_ELBO
。注意
派生类现在通过
__call__()
为(模型,指南)对提供了一个更符合PyTorch习惯的接口,这些对是Module
,这对于将Pyro的变分推断工具与标准PyTorch接口(如Optimizer
)以及像PyTorch Lightning和PyTorch JIT这样的大量库生态系统集成非常有用:model = Model() guide = pyro.infer.autoguide.AutoNormal(model) elbo_ = pyro.infer.Trace_ELBO(num_particles=10) # Fix the model/guide pair elbo = elbo_(model, guide) # perform any data-dependent initialization elbo(data) optim = torch.optim.Adam(elbo.parameters(), lr=0.001) for _ in range(100): optim.zero_grad() loss = elbo(data) loss.backward() optim.step()
请注意,在使用
PyroModule
时,Pyro的全局参数存储可能会导致这个新接口相对于标准PyTorch表现出意外的行为。因此,强烈建议用户在使用此接口时结合
pyro.settings.set(module_local_params=True)
,这将覆盖默认的跨PyroModule
实例的隐式参数共享。- Parameters
num_particles – 用于形成ELBO(梯度)估计器的粒子/样本数量。
max_plate_nesting (int) – 可选的最大嵌套
pyro.plate()
上下文数量的限制。这仅在并行枚举样本站点时需要,例如,如果一个站点设置了infer={"enumerate": "parallel"}
。如果省略,ELBO可能会通过运行一次(模型,指南)对来猜测一个有效的值,但是如果模型或指南结构是动态的,这个猜测可能是错误的。vectorize_particles (bool) – 是否在num_particles上向量化ELBO计算。默认为False。这需要在模型和指南中具有静态结构。
strict_enumeration_warning (bool) – 是否警告可能的枚举误用,即只有在存在枚举样本站点时才会使用
pyro.infer.traceenum_elbo.TraceEnum_ELBO
。ignore_jit_warnings (bool) – 忽略JIT跟踪器警告的标志。当此标志为True时,所有
torch.jit.TracerWarning
将被忽略。默认为False。jit_options (bool) – 可选的字典选项传递给
torch.jit.trace()
, 例如{"check_trace": True}
.retain_graph (bool) – 是否在SVI步骤中保留自动求导图。默认为None(False)。
tail_adaptive_beta (float) – 指数 beta,其中
-1.0 <= beta < 0.0
用于 与 TraceTailAdaptive_ELBO 一起使用。
参考文献
[1] 概率编程中的自动变分推断 David Wingate, Theo Weber
[2] 黑箱变分推断, Rajesh Ranganath, Sean Gerrish, David M. Blei
- class Trace_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[source]¶
基础类:
pyro.infer.elbo.ELBO
基于ELBO的SVI的跟踪实现。估计器的构建参考了文献[1]和[2]。模型或指南的依赖结构没有限制。梯度估计器包括部分Rao-Blackwell化,以减少存在不可重参数化随机变量时估计器的方差。Rao-Blackwell化是部分的,因为它仅使用由
plate
上下文标记的条件独立性信息。有关更细粒度的Rao-Blackwell化,请参见TraceGraph_ELBO
。参考文献
- [1] Automated Variational Inference in Probabilistic Programming,
大卫·温盖特, 西奥·韦伯
- [2] Black Box Variational Inference,
拉杰什·兰加纳特,肖恩·格里什,大卫·M·布莱
- class JitTrace_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础:
pyro.infer.trace_elbo.Trace_ELBO
类似于
Trace_ELBO
,但使用pyro.ops.jit.compile()
来编译loss_and_grads()
。这仅适用于有限的模型集:
模型必须具有静态结构。
模型不得依赖任何全局数据(除了参数存储)。
所有作为张量的模型输入必须通过
*args
传递。所有不是张量的模型输入必须通过
**kwargs
传递,并且每次唯一的**kwargs
都会触发编译。
- class TrackNonReparam[source]¶
基础类:
pyro.poutine.messenger.Messenger
跟踪不可重新参数化的样本点。
参考文献:
- Nonstandard Interpretations of Probabilistic Programs for Efficient Inference,
大卫·温盖特, 诺亚·古德曼, 安德烈亚斯·斯图尔穆勒, 杰弗里·西斯金德
示例:
>>> import torch >>> import pyro >>> import pyro.distributions as dist >>> from pyro.infer.tracegraph_elbo import TrackNonReparam >>> from pyro.ops.provenance import get_provenance >>> from pyro.poutine import trace >>> def model(): ... probs_a = torch.tensor([0.3, 0.7]) ... probs_b = torch.tensor([[0.1, 0.9], [0.8, 0.2]]) ... probs_c = torch.tensor([[0.5, 0.5], [0.6, 0.4]]) ... a = pyro.sample("a", dist.Categorical(probs_a)) ... b = pyro.sample("b", dist.Categorical(probs_b[a])) ... pyro.sample("c", dist.Categorical(probs_c[b]), obs=torch.tensor(0)) >>> with TrackNonReparam(): ... model_tr = trace(model).get_trace() >>> model_tr.compute_log_prob() >>> print(get_provenance(model_tr.nodes["a"]["log_prob"])) frozenset({'a'}) >>> print(get_provenance(model_tr.nodes["b"]["log_prob"])) frozenset({'b', 'a'}) >>> print(get_provenance(model_tr.nodes["c"]["log_prob"])) frozenset({'b', 'a'})
- class TraceGraph_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[source]¶
基础类:
pyro.infer.elbo.ELBO
基于ELBO的SVI的TraceGraph实现。梯度估计器是按照参考文献[1]的思路构建的,专门针对ELBO的情况。它支持模型和指南的任意依赖结构,以及不可重参数化随机变量的基线。
Trace
中记录的细粒度条件依赖信息用于减少梯度估计器的方差。特别是,使用来源跟踪[3]来找到依赖于每个不可重参数化样本点的cost
项。参考文献
- [1] Gradient Estimation Using Stochastic Computation Graphs,
约翰·舒尔曼,尼古拉斯·希斯,西奥芬·韦伯,彼得·阿比尔
- [2] Neural Variational Inference and Learning in Belief Networks
安德里·姆尼赫,卡罗尔·格雷戈尔
- [3] Nonstandard Interpretations of Probabilistic Programs for Efficient Inference,
大卫·温盖特, 诺亚·古德曼, 安德烈亚斯·斯图尔穆勒, 杰弗里·西斯金德
- class JitTraceGraph_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础:
pyro.infer.tracegraph_elbo.TraceGraph_ELBO
类似于
TraceGraph_ELBO
,但使用torch.jit.trace()
来编译loss_and_grads()
。这仅适用于有限的模型集:
模型必须具有静态结构。
模型不得依赖任何全局数据(除了参数存储)。
所有作为张量的模型输入必须通过
*args
传递。所有不是张量的模型输入必须通过
**kwargs
传递,并且每次唯一的**kwargs
都会触发编译。
- class BackwardSampleMessenger(enum_trace, guide_trace)[source]¶
基础类:
pyro.poutine.messenger.Messenger
实现前向滤波/后向采样,用于从联合后验分布中采样
- class TraceEnum_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础类:
pyro.infer.elbo.ELBO
基于ELBO的SVI的跟踪实现,支持 - 对离散采样点的详尽枚举,以及 - 在指南中的任何采样点上进行局部并行采样。
要在
guide
中对一个样本站点进行枚举,可以使用infer={'enumerate': 'sequential'}
或infer={'enumerate': 'parallel'}
标记该站点。要一次性配置所有guide站点, 请使用config_enumerate()
。要在model
中对一个样本站点进行枚举, 请使用infer={'enumerate': 'parallel'}
标记该站点,并确保该站点不出现在guide
中。这假设模型和指南具有受限的依赖结构:
plate
之外的变量永远不能依赖于该plate
内的变量。- loss(model, guide, *args, **kwargs)[source]¶
- Returns
ELBO的估计值
- Return type
使用
num_particles
多个样本(粒子)估计ELBO。
- differentiable_loss(model, guide, *args, **kwargs)[source]¶
- Returns
ELBO的可微分估计
- Return type
- Raises
ValueError – 如果ELBO不可微分(例如完全为零)
使用
num_particles
多个样本(粒子)估计一个可微分的ELBO。结果应该是无限可微分的(只要底层导数已经实现)。
- loss_and_grads(model, guide, *args, **kwargs)[source]¶
- Returns
ELBO的估计值
- Return type
使用
num_particles
多个样本(粒子)估计ELBO。对每个粒子的ELBO执行反向传播。
- class JitTraceEnum_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础类:
pyro.infer.traceenum_elbo.TraceEnum_ELBO
类似于
TraceEnum_ELBO
,但使用pyro.ops.jit.compile()
来编译loss_and_grads()
。这仅适用于有限的模型集:
模型必须具有静态结构。
模型不得依赖任何全局数据(除了参数存储)。
所有作为张量的模型输入必须通过
*args
传递。所有不是张量的模型输入必须通过
**kwargs
传递,并且每次唯一的**kwargs
都会触发编译。
- class TraceMeanField_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础:
pyro.infer.trace_elbo.Trace_ELBO
基于ELBO的SVI的跟踪实现。这是目前Pyro中唯一一个在可用时使用解析KL散度的ELBO估计器。
与例如
TraceGraph_ELBO
和Trace_ELBO
相比,此估计器对模型和指南的依赖结构施加了限制。 特别是它假设指南具有均值场结构, 即它在指南中存在的不同潜在变量之间进行分解。它还假设指南中的所有潜在变量都被重新参数化。后一个条件对于例如 正态分布是满足的,但对于例如 分类分布则不满足。警告
如果平均场条件不满足,此估计器可能会给出错误的结果。
高级用户注意:
平均场条件是此估计器正确的充分但不必要条件。精确的条件是,对于指南中的每个潜在变量z,其在模型中的父节点不得包括指南中z的任何后代潜在变量。这里的“模型中的父节点”和“指南中的后代”是相对于相应的(统计)依赖结构而言的。例如,如果模型和指南具有相同的依赖结构,则此条件始终满足。
- class JitTraceMeanField_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础:
pyro.infer.trace_mean_field_elbo.TraceMeanField_ELBO
类似于
TraceMeanField_ELBO
,但使用pyro.ops.jit.trace()
来编译loss_and_grads()
。这仅适用于有限的模型集:
模型必须具有静态结构。
模型不得依赖任何全局数据(除了参数存储)。
所有作为张量的模型输入必须通过
*args
传递。所有不是张量的模型输入必须通过
**kwargs
传递,并且每次唯一的**kwargs
都会触发编译。
- class TraceTailAdaptive_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[source]¶
基础:
pyro.infer.trace_elbo.Trace_ELBO
用于具有自适应f-散度的随机变分推断的接口,如参考文献[1]中所述。用户应指定num_particles > 1和vectorize_particles==True。可以指定参数tail_adaptive_beta来修改自适应f-散度的构建方式。详情请参阅参考文献。
请注意,此接口不支持计算变分目标本身;而是仅支持计算变分目标的梯度。因此,可能需要使用另一个SVI接口(例如RenyiELBO)以监控收敛性。
请注意,此接口仅支持所有潜在变量完全重新参数化的模型。它也不支持数据子采样。
参考文献 [1] “使用尾部自适应f-散度的变分推断”, Dilin Wang, Hao Liu, Qiang Liu, NeurIPS 2018 https://papers.nips.cc/paper/7816-variational-inference-with-tail-adaptive-f-divergence
- class RenyiELBO(alpha=0, num_particles=2, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True)[源代码]¶
基础类:
pyro.infer.elbo.ELBO
Renyi的\(\alpha\)-散度变分推断的实现,参考[1]。
为了使目标成为一个严格的下界,我们要求 \(\alpha \ge 0\)。然而,需要注意的是,根据参考文献[1],根据数据集的不同, \(\alpha < 0\) 可能会给出更好的结果。在特殊情况下 \(\alpha = 0\),目标函数是参考文献[2]中推导的重要加权自编码器的目标函数。
注意
设置 \(\alpha < 1\) 比通常的 ELBO 提供了更好的界限。 对于 \(\alpha = 1\),最好使用
Trace_ELBO
类,因为它有助于减少梯度估计的方差。- Parameters
alpha (float) – \(\alpha\)-散度的阶数。这里 \(\alpha \neq 1\)。默认值为0。
num_particles – 用于形成目标(梯度)估计器的粒子/样本数量。默认值为2。
max_plate_nesting (int) – 最大嵌套次数的限制
pyro.plate()
上下文。默认值为无穷大。strict_enumeration_warning (bool) – 是否警告可能的枚举误用,即只有在存在枚举样本站点时使用
TraceEnum_ELBO
。
参考文献:
- [1] Renyi Divergence Variational Inference,
李英珍, 理查德·E·特纳
- [2] Importance Weighted Autoencoders,
尤里·布尔达,罗杰·格罗斯,鲁斯兰·萨拉赫丁诺夫
- class TraceTMC_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[source]¶
基础类:
pyro.infer.elbo.ELBO
基于轨迹的张量蒙特卡洛实现 [1] 通过张量变量消除 [2] 支持: - 在模型或指南中的任何采样点上进行局部并行采样 - 在模型或指南中的任何采样点上进行穷举枚举
要获取多个样本,请使用
infer={'enumerate': 'parallel', 'num_samples': N}
标记站点。 要一次性配置模型或指南中的所有站点, 请使用config_enumerate()
。 要在model
中枚举或采样一个样本站点, 请标记该站点并确保该站点不出现在guide
中。这假设模型和指南具有受限的依赖结构:
plate
之外的变量永远不能依赖于 该plate
内的变量。参考文献
- [1] Tensor Monte Carlo: Particle Methods for the GPU Era,
劳伦斯·艾奇逊 (2018)
- [2] Tensor Variable Elimination for Plated Factor Graphs,
弗里茨·奥伯迈尔, 伊莱·宾厄姆, 马丁·扬科维亚克, 贾斯汀·邱, 尼尔拉吉·普拉丹, 亚历山大·拉什, 诺亚·古德曼 (2019)
- differentiable_loss(model, guide, *args, **kwargs)[source]¶
- Returns
边际对数似然的可微估计
- Return type
- Raises
ValueError – 如果ELBO不可微分(例如完全为零)
使用
num_particles
多个样本(粒子)计算可微分的TMC估计。结果应该是无限可微分的(只要底层导数已实现)。
重要性¶
- class Importance(model, guide=None, num_samples=None)[source]¶
基础类:
pyro.infer.abstract_infer.TracePosterior
,pyro.infer.importance.LogWeightsMixin
- Parameters
model – 定义为函数的概率模型
guide – 用于采样的指南,定义为函数
num_samples – 从指南中抽取的样本数量(默认值为10)
该方法通过重要性采样执行后验推断,使用指南作为提议分布。 如果没有提供指南,则默认从模型的先验中提议。
- log_weights: Union[List[Union[float, torch.Tensor]], torch.Tensor]¶
- class LogWeightsMixin[source]¶
基础类:
object
用于从
.log_weights
属性计算分析的Mixin类。- log_weights: Union[List[Union[float, torch.Tensor]], torch.Tensor]¶
- psis_diagnostic(model, guide, *args, **kwargs)[source]¶
使用[1]中描述的技术计算模型/指导对的Pareto尾部指数k,该技术建立在[2]中的先前工作基础上。如果\(0 < k < 0.5\),则指导是模型后验的良好近似,如[1]中所述。如果\(0.5 \le k \le 0.7\),则指导提供了次优的后验近似,但在实践中可能仍然有用。如果\(k > 0.7\),则指导程序提供了对完整后验的较差近似,使用指导时应谨慎。然而,请注意,即使指导对完整后验的拟合较差,仍可能产生合理的模型预测。如果\(k < 0.0\),则模型和指导的重要性权重似乎从上方有界;这对于通过ELBO最大化训练的指导来说将是一个奇怪的结果。请参阅[1]以获取关于如何解释尾部指数k的更完整讨论。
请注意,可能需要大量样本才能准确估计k。
请注意,我们假设模型和指南都是向量化的,并且具有静态结构。正如Pyro中的规范一样,args和kwargs被传递给模型和指南。
参考文献 [1] ‘是的,但它有效吗?:评估变分推断。’ Yuling Yao, Aki Vehtari, Daniel Simpson, Andrew Gelman [2] ‘帕累托平滑重要性采样。’ Aki Vehtari, Andrew Gelman, Jonah Gabry
- Parameters
- Returns float
PSIS诊断k
重加权唤醒-睡眠¶
- class ReweightedWakeSleep(num_particles=2, insomnia=1.0, model_has_params=True, num_sleep_particles=None, vectorize_particles=True, max_plate_nesting=inf, strict_enumeration_warning=True)[source]¶
基础类:
pyro.infer.elbo.ELBO
根据参考文献[1]实现的重加权唤醒睡眠算法。
注意
采样和log_prob评估的渐近复杂度:
- Using wake-theta and/or wake-phi
从指南中抽取O(num_particles)个样本, 对模型和指南进行O(num_particles)次log_prob评估
- Using sleep-phi
从模型中抽取O(num_sleep_particles)个样本, 对引导进行O(num_sleep_particles)次log_prob评估
- if 1) and 2) are combined,
从指南中抽取O(num_particles)个样本, 从模型中抽取O(num_sleep_particles)个样本, 对指南进行O(num_particles + num_sleep_particles)次log_prob评估,以及 对模型进行O(num_particles)次评估
注意
这对于具有随机分支的模型特别有用,如[2]中所述。
注意
这将返回两种损失,一种是模型参数(theta)的损失,使用iwae目标计算,另一种是指导参数(phi)的损失,使用csis目标和自归一化重要性采样版本的csis目标的组合计算。
注意
为了能够计算睡眠-phi项,指南程序必须通过关键字参数observations显式传递其观察值。如果在定义期间观察值未知,例如在摊销变分推断中,可以将其默认参数设置为observations=None,并在学习期间通过svi.step(observations=…)提供正确的值。
警告
目前还不支持小批量训练。
- Parameters
num_particles (int) – 用于形成目标(梯度)估计器的粒子/样本数量。默认值为2。
失眠 – 清醒-phi 和睡眠-phi 项之间的比例。默认值为 1.0 [wake-phi]
model_has_params (bool) – 指示模型是否具有可学习的参数。在纯睡眠模式[csis]下运行时,避免额外计算非常有用。默认值为True。
num_sleep_particles (int) – 用于形成睡眠-phi估计器的粒子数量。 默认情况下与num_particles匹配。
vectorize_particles (bool) – 是否应该在num_particles之间对轨迹进行向量化。默认值为True。
max_plate_nesting (int) – 最大嵌套次数的限制
pyro.plate()
上下文。默认值为无穷大。strict_enumeration_warning (bool) – 是否警告可能的枚举误用,即只有在存在枚举样本站点时使用
TraceEnum_ELBO
。
参考文献:
- [1] Reweighted Wake-Sleep,
约尔格·博恩沙因, 约书亚·本吉奥
- [2] Revisiting Reweighted Wake-Sleep for Models with Stochastic Control Flow,
团安·勒,亚当·R·科西奥雷克,N·西达尔特,伊·怀·特,弗兰克·伍德
序贯蒙特卡洛¶
- exception SMCFailed[source]¶
基础类:
ValueError
当
SMCFilter
未能找到任何具有非零概率的假设时引发的异常。
- class SMCFilter(model, guide, num_particles, max_plate_nesting, *, ess_threshold=0.5)[source]¶
基础类:
object
SMCFilter
是通过顺序蒙特卡洛进行过滤的顶级接口。模型和指南应该是具有两个方法的对象:
.init(state, ...)
和.step(state, ...)
,旨在首先调用init()
,然后重复调用step()
。这两个 方法应该具有与SMCFilter
的init()
和step()
相同的签名,但有一个额外的第一个 参数state
,应该用于存储所有依赖于采样变量的张量。state
将是一个类似字典的对象,SMCState
,具有任意键和torch.Tensor
值。 模型可以读取和写入state
,但指南只能从中读取。推理复杂度是
O(len(state) * num_time_steps)
,因此为了避免马尔可夫模型中的二次复杂度,确保state
具有固定大小。- Parameters
斯坦方法¶
- class IMQSteinKernel(alpha=0.5, beta=- 0.5, bandwidth_factor=None)[source]¶
基础类:
pyro.infer.svgd.SteinKernel
用于SVGD推理算法的IMQ(逆多二次)核[1]。核的带宽是根据参考[2]中的简单启发式方法从粒子中选择的。核的形式为
\(K(x, y) = (\alpha + ||x-y||^2/h)^{\beta}\)
其中 \(\alpha\) 和 \(\beta\) 是用户指定的参数,\(h\) 是带宽。
- Parameters
- Variables
bandwidth_factor (float) – 控制每次迭代时带宽缩放比例的属性。
参考文献
[1] “Stein Points,” Wilson Ye Chen, Lester Mackey, Jackson Gorham, Francois-Xavier Briol, Chris. J. Oates. [2] “Stein变分梯度下降:一种通用的贝叶斯推理算法,” Qiang Liu, Dilin Wang
- property bandwidth_factor¶
- class RBFSteinKernel(bandwidth_factor=None)[源代码]¶
基础类:
pyro.infer.svgd.SteinKernel
用于SVGD推理算法的RBF核。核的带宽是根据参考文献[1]中的简单启发式方法从粒子中选择的。
- Parameters
bandwidth_factor (float) – 可选的带宽缩放因子,默认为1.0。
- Variables
bandwidth_factor (float) – 控制每次迭代时带宽缩放比例的属性。
参考文献
- [1] “Stein Variational Gradient Descent: A General Purpose Bayesian Inference Algorithm,”
刘强,王迪林
- property bandwidth_factor¶
- class SVGD(model, kernel, optim, num_particles, max_plate_nesting, mode='univariate')[source]¶
基础类:
object
Stein变分梯度下降的基本实现,如参考文献[1]中所述。
- Parameters
model – 模型(包含Pyro原语的可调用对象)。模型必须完全向量化,并且只能包含连续的潜在变量。
kernel – 一个与SVGD兼容的内核,如
RBFSteinKernel
。optim (pyro.optim.PyTorch优化器的包装器) – 一个用于PyTorch优化器的包装器。
num_particles (int) – 在SVGD中使用的粒子数量。
max_plate_nesting (int) – 模型中嵌套的
pyro.plate()
上下文的最大数量。mode (str) – 是否使用利用多元测试函数(如[1]中所述)或一元测试函数(如[2]中所述)的核化Stein差异。默认为一元。
示例用法:
from pyro.infer import SVGD, RBFSteinKernel from pyro.optim import Adam kernel = RBFSteinKernel() adam = Adam({"lr": 0.1}) svgd = SVGD(model, kernel, adam, num_particles=50, max_plate_nesting=0) for step in range(500): svgd.step(model_arg1, model_arg2) final_particles = svgd.get_named_particles()
参考文献
- [1] “Stein Variational Gradient Descent: A General Purpose Bayesian Inference Algorithm,”
刘强,王迪林
- [2] “Kernelized Complete Conditional Stein Discrepancy,”
拉加夫·辛哈尔, 萨阿德·拉赫卢, 拉杰什·兰加纳特
无似然方法¶
- class EnergyDistance(beta=1.0, prior_scale=0.0, num_particles=2, max_plate_nesting=inf)[source]¶
基础类:
object
后验预测能量距离 [1,2],可选择通过先验进行贝叶斯正则化。
让 p(x,z)=p(z) p(x|z) 成为模型,q(z|x) 成为指南。然后给定数据 x 并绘制一个独立同分布的样本对 \((Z,X)\) 和 \((Z',X')\)(其中 Z 是隐变量,X 是后验预测),
\[\begin{split}& Z \sim q(z|x); \quad X \sim p(x|Z) \\ & Z' \sim q(z|x); \quad X' \sim p(x|Z') \\ & loss = \mathbb E_X \|X-x\|^\beta - \frac 1 2 \mathbb E_{X,X'}\|X-X'\|^\beta - \lambda \mathbb E_Z \log p(Z)\end{split}\]这是一种无似然推断算法,可以用于没有易处理的密度函数的似然。\(\beta\) 能量距离是一种鲁棒的损失函数,对于任何具有有限分数矩 \(\mathbb E[\|X\|^\beta]\) 的分布都有良好的定义。
这需要静态模型结构、完全重新参数化的指南以及模型中重新参数化的似然分布。模型的潜在分布可能未重新参数化。
参考文献
- [1] Gabor J. Szekely, Maria L. Rizzo (2003)
能源统计:基于距离的一类统计。
- [2] Tilmann Gneiting, Adrian E. Raftery (2007)
严格适当的评分规则、预测和估计。 https://www.stat.washington.edu/raftery/Research/PDF/Gneiting2007jasa.pdf
- Parameters
beta (float) – 指数 \(\beta\) 来自 [1,2]。损失函数对于具有有限 \(beta\)-绝对矩的分布是严格合适的 \(E[\|X\|^\beta]\)。因此,对于重尾分布,
beta
应该 较小,例如对于Cauchy
分布,\(\beta<1\) 是严格 合适的。默认为 1。必须在开区间 (0,2) 内。prior_scale (float) – 用于先验正则化的非负尺度。 仅当此值为正时,模型参数才会被训练。 如果为零(默认值),则不会计算模型的对数密度 (指南的对数密度从不计算)。
num_particles (int) – 用于形成梯度估计器的粒子/样本数量。必须至少为2。
max_plate_nesting (int) – 可选的最大嵌套层数限制
pyro.plate()
上下文。如果省略,将通过运行一次(模型,指南)对来猜测一个有效值。
离散推理¶
- infer_discrete(fn=None, first_available_dim=None, temperature=1, *, strict_enumeration_warning=True)[source]¶
一种从后验中采样标记为
site["infer"]["enumerate"] = "parallel"
的离散站点的poutine,基于观察条件。示例:
@infer_discrete(first_available_dim=-1, temperature=0) @config_enumerate def viterbi_decoder(data, hidden_dim=10): transition = 0.3 / hidden_dim + 0.7 * torch.eye(hidden_dim) means = torch.arange(float(hidden_dim)) states = [0] for t in pyro.markov(range(len(data))): states.append(pyro.sample("states_{}".format(t), dist.Categorical(transition[states[-1]]))) pyro.sample("obs_{}".format(t), dist.Normal(means[states[-1]], 1.), obs=data[t]) return states # returns maximum likelihood states
- class TraceEnumSample_ELBO(num_particles=1, max_plate_nesting=inf, max_iarange_nesting=None, vectorize_particles=False, strict_enumeration_warning=True, ignore_jit_warnings=False, jit_options=None, retain_graph=None, tail_adaptive_beta=- 1.0)[源代码]¶
基础类:
pyro.infer.traceenum_elbo.TraceEnum_ELBO
这扩展了
TraceEnum_ELBO
,使其在SVI期间从离散潜在状态采样时更加经济。以下是等价的,但第一种方法更便宜,它在计算
loss
和z
之间共享工作:# Version 1. elbo = TraceEnumSample_ELBO(max_plate_nesting=1) loss = elbo.loss(*args, **kwargs) z = elbo.sample_saved() # Version 2. elbo = TraceEnum_ELBO(max_plate_nesting=1) loss = elbo.loss(*args, **kwargs) guide_trace = poutine.trace(guide).get_trace(*args, **kwargs) z = infer_discrete(poutine.replay(model, guide_trace), first_available_dim=-2)(*args, **kwargs)
预测工具¶
- class MHResampler(sampler: Callable, source_samples_slice: slice = slice(None, 0, None), stored_samples_slice: slice = slice(None, 0, None))[source]¶
基础类:
torch.nn.modules.module.Module
用于加权样本的重采样器,从由加权样本
sampler
指定的分布中生成等权样本。重采样基于Metropolis-Hastings算法。 给定初始样本 \(x\),后续样本通过以下方式生成:
从
guide
中采样一个新的候选样本\(x'\),其概率为\(g(x')\)。计算接受概率 \(A(x', x) = \min\left(1, \frac{P(x')}{P(x)} \frac{g(x)}{g(x')}\right)\) 其中 \(P\) 是
model
。以概率 \(A(x', x)\) 接受新的样本候选 \(x'\) 作为下一个样本,否则将当前样本 \(x\) 设为下一个样本。
以上是Metropolis-Hastings算法,其中新的样本候选提议分布等于
guide
,并且独立于当前样本,使得\(g(x')=g(x' \mid x)\)。- Parameters
采样器 (可调用) – 当被调用时返回
WeighedPredictiveResults
。source_samples_slice (slice) – 选择用于存储的源样本(默认为 slice(0),即不选择)。
stored_samples_slice (slice) – 选择要存储的输出样本(默认为slice(0),即不存储)。
MHResampler
的典型用例是将由WeighedPredictive
生成的加权样本转换为来自目标分布的等权重样本。 每次调用MHResampler
的实例时,它都会返回一组新的样本,第一次调用生成的样本根据guide
分布,而每次后续调用时,样本的分布会越来越接近后验预测分布。 可能需要一些实验来确定在每种情况下需要调用MHResampler
实例多少次才能足够接近后验预测分布。示例:
def model(): ... def guide(): ... def conditioned_model(): ... # Fit guide elbo = Trace_ELBO(num_particles=100, vectorize_particles=True) svi = SVI(conditioned_model, guide, optim.Adam(dict(lr=3.0)), elbo) for i in range(num_svi_steps): svi.step() # Create callable that returns weighed samples posterior_predictive = WeighedPredictive(model, guide=guide, num_samples=num_samples, parallel=parallel, return_sites=["_RETURN"]) prob = 0.95 weighed_samples = posterior_predictive(model_guide=conditioned_model) # Calculate quantile directly from weighed samples weighed_samples_quantile = weighed_quantile(weighed_samples.samples['_RETURN'], [prob], weighed_samples.log_weights)[0] resampler = MHResampler(posterior_predictive) num_mh_steps = 10 for mh_step_count in range(num_mh_steps): resampled_weighed_samples = resampler(model_guide=conditioned_model) # Calculate quantile from resampled weighed samples (samples are equally weighed) resampled_weighed_samples_quantile = quantile(resampled_weighed_samples.samples[`_RETURN`], [prob])[0] # Quantiles calculated using both methods should be identical assert_close(weighed_samples_quantile, resampled_weighed_samples_quantile, rtol=0.01)
采样器行为注意事项:
如果
guide
完美地跟踪model
,这个采样器将不会做任何事情,因为接受概率\(A(x', x)\)将始终为一。此外,如果指南大致可分离,即 \(g(z_A, z_B) \approx g_A(z_A) g_B(z_B)\), 其中 \(g_A(z_A)\) 完美跟踪
model
而 \(g_B(z_B)\) 跟踪model
的效果较差, 从MHResampler
中抽取的样本计算的 \(z_A\) 的分位数将比使用weighed_quantile
计算的 \(z_A\) 的分位数具有更低的方差, 因为使用weighed_quantile
计算的有效样本量会由于 \(g_B(z_B)\) 对model
的跟踪效果较差而较低, 而使用MHResampler
时,\(g_B(z_B)\) 对model
的跟踪效果较差对 \(z_A\) 样本的有效样本量的影响可以忽略不计。
- forward(*args, **kwargs)[source]¶
执行单次重采样步骤。 返回
WeighedPredictiveResults
- class Predictive(model, posterior_samples=None, guide=None, num_samples=None, return_sites=(), parallel=False)[source]¶
基础类:
torch.nn.modules.module.Module
实验类用于构建预测分布。预测分布是通过运行model,以posterior_samples中的潜在样本为条件获得的。如果提供了guide,则还会返回所有潜在站点的后验样本。
警告
Predictive
类的接口是实验性的,未来可能会发生变化。- Parameters
model – 包含Pyro原语的Python可调用对象。
posterior_samples (dict) – 来自后验的样本字典。
指南 (可调用) – 可选的指南,用于获取不在posterior_samples中的站点的后验样本。
num_samples (int) – 从预测分布中抽取的样本数量。 如果
posterior_samples
不为空,则此参数无效,此时将使用posterior_samples
中样本的前导维度大小。return_sites (list, tuple, 或 set) – 要返回的站点;默认情况下,仅返回不在posterior_samples中的样本站点。
parallel (bool) – 通过将现有模型包装在最外层的 plate 信使中来并行预测。请注意,这要求模型通过
plate
正确注释了所有批次维度。默认值为 False。
- call(*args, **kwargs)[source]¶
调用
forward()
并将引导的参数值作为tuple而不是dict返回的方法,这是JIT跟踪的要求。与forward()
不同,此方法可以通过torch.jit.trace_module()
进行跟踪。警告
一旦PyTorch JIT追踪器开始接受dict作为有效的返回类型,此方法可能会被移除。参见issue。
- forward(*args, **kwargs)[source]¶
返回预测分布中的样本字典。默认情况下,仅返回不包含在posterior_samples中的样本站点。可以通过更改此
Predictive
实例的return_sites关键字参数来修改此行为。注意
此方法由
Module
内部使用。 用户应改用__call__()
,如Predictive(model)(*args, **kwargs)
所示。- Parameters
args – 模型参数。
kwargs – 模型关键字参数。
- class WeighedPredictive(model, posterior_samples=None, guide=None, num_samples=None, return_sites=(), parallel=False)[source]¶
基础类:
pyro.infer.predictive.Predictive
用于构建基于加权预测分布的类,该分布使用与
Predictive
相同的初始化接口。方法 .forward 和 .call 可以使用一个额外的关键字参数
model_guide
来调用,该参数是用于创建和优化指南的模型(如果未提供,model_guide
默认为self.model
),并且它们返回样本和 log_weights。权重计算为模型指南对数概率和指南对数概率之间的每个样本差距(必须始终提供指南)。
一个典型的用例将基于一个
model
\(p(x,z)=p(x|z)p(z)\)和一个guide
\(q(z)\) ,该模型已经拟合到给定观测值\(p(X_{obs},z)\)的模型,这两者在初始化WeighedPredictive
时提供(与使用Predictive
时相同)。 当调用WeighedPredictive
的实例时,我们提供给定观测值\(p(X_{obs},z)\)的模型 作为关键字参数model_guide
。 结果输出将是通常的样本\(p(x|z)q(z)\),由Predictive
返回, 以及每个样本的权重\(p(X_{obs},z)/q(z)\)。样本和权重可以输入到weighed_quantile
中,以获得结果分布的真实分位数。请注意,
model
可以更加复杂,包含未观察到的样本点 \(y\),这些样本点不属于指南的一部分,如果样本点 \(y\) 在观察之后被采样,并且由指南采样的潜在变量,使得 \(p(x,y,z)=p(y|x,z)p(x|z)p(z)\),其中乘积中的每个元素代表一组pyro.sample
语句。- call(*args, **kwargs)[source]¶
方法 .call 向后兼容在
Predictive
中找到的相同方法 但可以使用额外的关键字参数 model_guide 调用 这是用于创建和优化指南的模型。返回
WeighedPredictiveResults
,它具有属性.samples
和每个样本的权重.log_weights
。
- forward(*args, **kwargs)[source]¶
方法 .forward 向后兼容在
Predictive
中找到的相同方法 但可以使用额外的关键字参数 model_guide 调用 该参数是用于创建和优化指南的模型。返回
WeighedPredictiveResults
,它具有属性.samples
和每个样本的权重.log_weights
。
- class WeighedPredictiveResults(samples: Union[dict, tuple], log_weights: torch.Tensor, guide_log_prob: torch.Tensor, model_log_prob: torch.Tensor)[源代码]¶
基础类:
pyro.infer.importance.LogWeightsMixin
,pyro.infer.util.CloneMixin
返回对
WeighedPredictive
实例的调用值。- guide_log_prob: torch.Tensor¶
- log_weights: torch.Tensor¶
- model_log_prob: torch.Tensor¶
- class EmpiricalMarginal(trace_posterior, sites=None, validate_args=None)[源代码]¶
基础类:
pyro.distributions.distribution.Distribution
,Callable
从
TracePosterior
的模型中提取单个站点(或多个站点,前提是它们具有相同的形状)的边际分布。- Parameters
trace_posterior (TracePosterior) – 一个
TracePosterior
实例,表示 一个蒙特卡罗后验。sites (list) – 可选的站点列表,我们需要为其生成边际分布。
- class Marginals(trace_posterior, sites=None, validate_args=None)[source]¶
基础类:
object
保存来自
TracePosterior
模型的一个或多个站点的边际分布。这是一个方便的容器类,可以由TracePosterior
子类扩展。例如,用于实现诊断。- Parameters
trace_posterior (TracePosterior) – 一个表示蒙特卡洛后验的TracePosterior实例。
sites (list) – 可选的站点列表,我们需要为其生成边际分布。
- property empirical¶
一个包含站点名称及其对应的
EmpiricalMarginal
分布的字典。- Type
OrderedDict
- class TracePosterior(num_chains=1)[source]¶
基础类:
object
抽象TracePosterior对象,后验推理算法从中继承。 运行时,从近似后验中收集一组执行轨迹。 这设计用于其他实用类,如EmpiricalMarginal, 这些类需要访问收集到的执行轨迹。
- information_criterion(pointwise=False)[source]¶
计算模型的信息准则。目前,仅返回“广泛适用/渡边-赤池信息准则”(WAIC)及相应的有效参数数量。
参考:
[1] 使用留一法交叉验证和WAIC进行实用贝叶斯模型评估, Aki Vehtari, Andrew Gelman, 和 Jonah Gabry
- Parameters
pointwise (bool) – 一个标志,用于决定我们是否想要获得一个向量化的WAIC。当
pointwise=False
时,返回总和。- Returns
一个包含WAIC值及其有效参数数量的字典。
- Return type
OrderedDict
- class TracePredictive(model, posterior, num_samples, keep_sites=None)[source]¶
基础类:
pyro.infer.abstract_infer.TracePosterior
警告
此类已弃用,并将在未来的版本中移除。 请改用
Predictive
类。生成并保存来自后验预测分布的轨迹,给定来自近似后验的模型执行轨迹。这是通过将潜在站点约束为从模型执行轨迹中随机采样的参数值,并向前运行模型以生成具有新响应(“_RETURN”)站点的轨迹来实现的。 :param model: 包含Pyro原语的任意Python可调用对象。 :param TracePosterior posterior: 保存模型近似后验样本的轨迹后验实例。 :param int num_samples: 要生成的样本数量。 :param keep_sites: 应从后验分布中采样的站点(默认:全部)