神经网络¶
模块 pyro.nn 提供了在深度概率编程中有用的神经网络模块实现。
Pyro 模块¶
Pyro 包含一个类 PyroModule
,它是 torch.nn.Module
的子类,其属性可以被 Pyro 效果修改。要创建 poutine 感知的属性,可以使用 PyroParam
结构体或 PyroSample
结构体。
my_module = PyroModule()
my_module.x = PyroParam(torch.tensor(1.), constraint=constraints.positive)
my_module.y = PyroSample(dist.Normal(0, 1))
- class PyroParam(init_value: Optional[Union[torch.Tensor, Callable[[], torch.Tensor]]] = None, constraint: torch.distributions.constraints.Constraint = Real(), event_dim: Optional[int] = None)[source]¶
基类:
tuple
声明
PyroModule
的一个由 Pyro 管理的可学习属性,类似于pyro.param
。这可以用来设置
PyroModule
实例的属性assert isinstance(my_module, PyroModule) my_module.x = PyroParam(torch.zeros(4)) # eager my_module.y = PyroParam(lambda: torch.randn(4)) # lazy my_module.z = PyroParam(torch.ones(4), # eager constraint=constraints.positive, event_dim=1)
或(实验性)作为惰性初始化属性的装饰器
class MyModule(PyroModule): @PyroParam def x(self): return torch.zeros(4) @PyroParam def y(self): return torch.randn(4) @PyroParam(constraint=constraints.real, event_dim=1) def z(self): return torch.ones(4) def forward(self): return self.x + self.y + self.z # accessed like a @property
- 参数
init_value (torch.Tensor 或 返回 torch.Tensor 的可调用对象 或 None) – 用于即时初始化的张量,用于惰性初始化的可调用对象,或用于作为装饰器的 None。
constraint (Constraint) – torch 约束,默认为
constraints.real
。event_dim (int) – (可选)与批处理无关的最右侧维度数量。此维度左侧的维度将被视为批处理维度;如果参数语句位于 subsampled plate 内部,则参数的相应批处理维度将相应地进行子采样。如果未指定,所有维度都将被视为事件维度,并且不执行子采样。
- init_value: Optional[Union[torch.Tensor, Callable[[], torch.Tensor]]]¶
字段编号 0 的别名
- constraint: torch.distributions.constraints.Constraint¶
字段编号 1 的别名
- class PyroSample(prior: Union[TorchDistributionMixin, Callable[[PyroModule], TorchDistributionMixin]])[source]¶
基类:
object
声明
PyroModule
的一个由 Pyro 管理的随机属性,类似于pyro.sample
。这可以用来设置
PyroModule
实例的属性assert isinstance(my_module, PyroModule) my_module.x = PyroSample(Normal(0, 1)) # independent my_module.y = PyroSample(lambda self: Normal(self.x, 1)) # dependent
或(实验性)作为惰性初始化方法的装饰器
class MyModule(PyroModule): @PyroSample def x(self): return Normal(0, 1) # independent @PyroSample def y(self): return Normal(self.x, 1) # dependent def forward(self): return self.y # accessed like a @property
- 参数
prior – 分布对象或函数,该函数接收
PyroModule
实例self
作为输入并返回一个分布对象。
- prior: Union[TorchDistributionMixin, Callable[[PyroModule], TorchDistributionMixin]]¶
- class PyroModule(name: str = '')[source]¶
基类:
torch.nn.modules.module.Module
torch.nn.Module
的子类,其属性可以被 Pyro 效果修改。属性可以使用辅助函数PyroParam
和PyroSample
设置,方法可以使用pyro_method()
装饰。参数
要创建 Pyro 管理的参数属性,可以使用
torch.nn.Parameter
(用于无约束参数)或PyroParam
(用于受约束参数)来设置该属性。读取该属性将触发pyro.param
语句。例如:# Create Pyro-managed parameter attributes. my_module = PyroModule() my_module.loc = nn.Parameter(torch.tensor(0.)) my_module.scale = PyroParam(torch.tensor(1.), constraint=constraints.positive) # Read the attributes. loc = my_module.loc # Triggers a pyro.param statement. scale = my_module.scale # Triggers another pyro.param statement.
注意,与普通的
torch.nn.Module
不同,PyroModule
不应该使用pyro.module
语句进行注册。PyroModule
可以包含其他的PyroModule
和普通的torch.nn.Module
。访问PyroModule
的一个普通torch.nn.Module
属性会触发一个pyro.module
语句。如果在一个 Pyro 模型或 guide 中出现多个PyroModule
,它们应该包含在该模型的单个根PyroModule
中。PyroModule
在每次setattr
、getattr
和delattr
事件时,根据属性的嵌套名称与 param store 同步数据。设置
mod.x = x_init
尝试从 param store 读取x
的值。如果在 param store 中找到值,则将该值复制到mod
中并忽略x_init
;否则将x_init
复制到mod
和 param store 中。读取
mod.x
尝试从 param store 读取x
的值。如果在 param store 中找到值,则将该值复制到mod
中;否则将mod
的值复制到 param store 中。最终mod
和 param store 会对返回的单个值达成一致。删除
del mod.x
会从mod
和 param store 中移除该值。
请注意,两个同名的
PyroModule
都会与全局 param store 同步,因此包含相同的数据。当创建一个PyroModule
,然后删除它,再创建另一个同名的PyroModule
时,后一个将从 param store 中填充前一个的数据。为了避免这种持久性,可以在删除PyroModule
之前调用pyro.clear_param_store()
或调用clear()
。PyroModule
可以直接使用torch.save()
/torch.load()
保存和加载,也可以间接使用 param store 的save()
/load()
方法。请注意,torch.load()
将被 param store 中的任何值覆盖,因此最安全的做法是在加载之前调用pyro.clear_param_store()
。采样
要创建 Pyro 管理的随机属性,请使用
PyroSample
辅助函数设置该属性,并指定一个先验分布。读取该属性将触发一个pyro.sample
语句。例如:# Create Pyro-managed random attributes. my_module.x = PyroSample(dist.Normal(0, 1)) my_module.y = PyroSample(lambda self: dist.Normal(self.loc, self.scale)) # Sample the attributes. x = my_module.x # Triggers a pyro.sample statement. y = my_module.y # Triggers one pyro.sample + two pyro.param statements.
采样在
.__call__()
的每次调用或由pyro_method()
装饰的方法内部被缓存。由于 sample 语句在 Pyro trace 中只能出现一次,您应该确保对 sample 属性的跟踪访问被封装在.__call__()
的单次调用或由pyro_method()
装饰的方法中。要使现有模块具有概率性,您可以创建一个子类,并使用
PyroSample
覆盖一些参数。class RandomLinear(nn.Linear, PyroModule): # used as a mixin def __init__(self, in_features, out_features): super().__init__(in_features, out_features) self.weight = PyroSample( lambda self: dist.Normal(0, 1) .expand([self.out_features, self.in_features]) .to_event(2))
Mixin 类
PyroModule
可以用作 mixin 类,并支持动态创建 mixin 的简单语法,例如以下两种方式是等效的:# Version 1. create a named mixin class class PyroLinear(nn.Linear, PyroModule): pass m.linear = PyroLinear(m, n) # Version 2. create a dynamic mixin class m.linear = PyroModule[nn.Linear](m, n)
这种表示法可以递归地用于创建贝叶斯模块,例如:
model = PyroModule[nn.Sequential]( PyroModule[nn.Linear](28 * 28, 100), PyroModule[nn.Sigmoid](), PyroModule[nn.Linear](100, 100), PyroModule[nn.Sigmoid](), PyroModule[nn.Linear](100, 10), ) assert isinstance(model, nn.Sequential) assert isinstance(model, PyroModule) # Now we can be Bayesian about weights in the first layer. model[0].weight = PyroSample( prior=dist.Normal(0, 1).expand([28 * 28, 100]).to_event(2)) guide = AutoDiagonalNormal(model)
注意,
PyroModule[...]
不会递归地将PyroModule
mixin 到输入Module
的子模块中;因此我们需要包装上面nn.Sequential
的每个子模块。- 参数
name (str) – 根 PyroModule 的可选名称。在其他 PyroModule 的子 PyroModule 中,此名称被忽略。
- add_module(name: str, module: Optional[torch.nn.modules.module.Module]) None [source]¶
向当前模块添加一个子模块。
- pyro_method(fn: Callable[[pyro.nn.module._PyroModule, pyro.nn.module._P], pyro.nn.module._T]) Callable[[pyro.nn.module._PyroModule, pyro.nn.module._P], pyro.nn.module._T] [source]¶
PyroModule
顶级方法的装饰器,用于启用 pyro 效果并缓存pyro.sample
语句。这应该应用于所有读取 Pyro 管理属性的公共方法,但
.forward()
不需要。
- clear(mod: pyro.nn.module.PyroModule) None [source]¶
从
PyroModule
和 param store 中移除数据。- 参数
mod (PyroModule) – 要清除的模块。
- to_pyro_module_(m: torch.nn.modules.module.Module, recurse: bool = True) None [source]¶
原地将普通的
torch.nn.Module
实例转换为PyroModule
。这对于向第三方模块添加 Pyro 效果非常有用:无需修改第三方代码。例如:
model = nn.Sequential( nn.Linear(28 * 28, 100), nn.Sigmoid(), nn.Linear(100, 100), nn.Sigmoid(), nn.Linear(100, 10), ) to_pyro_module_(model) assert isinstance(model, PyroModule[nn.Sequential]) assert isinstance(model[0], PyroModule[nn.Linear]) # Now we can attempt to be fully Bayesian: for m in model.modules(): for name, value in list(m.named_parameters(recurse=False)): setattr(m, name, PyroSample(prior=dist.Normal(0, 1) .expand(value.shape) .to_event(value.dim()))) guide = AutoDiagonalNormal(model)
- 参数
m (torch.nn.Module) – 模块实例。
recurse (bool) – 是否将子模块转换为
PyroModules
。
- class PyroModuleList(modules)[source]¶
基类:
torch.nn.modules.container.ModuleList
,pyro.nn.module.PyroModule
AutoRegressiveNN¶
- class AutoRegressiveNN(input_dim: int, hidden_dims: List[int], param_dims: List[int] = [1, 1], permutation: Optional[torch.LongTensor] = None, skip_connections: bool = False, nonlinearity: torch.nn.modules.module.Module = ReLU())[source]¶
基类:
pyro.nn.auto_reg_nn.ConditionalAutoRegressiveNN
MADE 风格自回归神经网络的实现。
示例用法
>>> x = torch.randn(100, 10) >>> arn = AutoRegressiveNN(10, [50], param_dims=[1]) >>> p = arn(x) # 1 parameters of size (100, 10) >>> arn = AutoRegressiveNN(10, [50], param_dims=[1, 1]) >>> m, s = arn(x) # 2 parameters of size (100, 10) >>> arn = AutoRegressiveNN(10, [50], param_dims=[1, 5, 3]) >>> a, b, c = arn(x) # 3 parameters of sizes, (100, 1, 10), (100, 5, 10), (100, 3, 10)
- 参数
input_dim (int) – 输入变量的维度
param_dims (list[int]) – 当 p_n > 1 时,将输出形状为 (p_n, input_dim) 的参数;当 p_n == 1 时,将输出形状为 (input_dim) 的参数。默认为 [1, 1],即输出两个维度为 (input_dim) 的参数,这对于逆自回归流非常有用。
permutation (torch.LongTensor) – 可选的排列,应用于输入并控制自回归分解的顺序。特别是对于单位排列,自回归结构使得雅可比矩阵是上三角的。默认情况下,此排列是随机选择的。
skip_connections (bool) – 是否添加从输入到输出的跳跃连接。
nonlinearity (torch.nn.module) – 前馈网络中使用的非线性激活函数,例如 torch.nn.ReLU()。注意,最终的网络输出没有应用非线性,因此输出是无界的实数。
参考
MADE: Masked Autoencoder for Distribution Estimation [arXiv:1502.03509] Mathieu Germain, Karol Gregor, Iain Murray, Hugo Larochelle
- forward(x: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶
DenseNN¶
- class DenseNN(input_dim: int, hidden_dims: List[int], param_dims: List[int] = [1, 1], nonlinearity: torch.nn.modules.module.Module = ReLU())[source]¶
基类:
pyro.nn.dense_nn.ConditionalDenseNN
一个简单密集前馈网络的实现,可用于例如一些条件流,如
pyro.distributions.transforms.ConditionalPlanarFlow
,以及其他不需要自回归网络的无条件流,如pyro.distributions.transforms.AffineCoupling
。示例用法
>>> input_dim = 10 >>> context_dim = 5 >>> z = torch.rand(100, context_dim) >>> nn = DenseNN(context_dim, [50], param_dims=[1, input_dim, input_dim]) >>> a, b, c = nn(z) # parameters of size (100, 1), (100, 10), (100, 10)
- 参数
- forward(x: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶
ConditionalAutoRegressiveNN¶
- class ConditionalAutoRegressiveNN(input_dim: int, context_dim: int, hidden_dims: List[int], param_dims: List[int] = [1, 1], permutation: Optional[torch.LongTensor] = None, skip_connections: bool = False, nonlinearity: torch.nn.modules.module.Module = ReLU())[source]¶
基类:
torch.nn.modules.module.Module
一个 MADE 风格自回归神经网络的实现,可以输入额外的上下文变量。(有关条件 MADE 架构工作原理的解释,请参见参考文献 [2] 第 3.3 节。)
示例用法
>>> x = torch.randn(100, 10) >>> y = torch.randn(100, 5) >>> arn = ConditionalAutoRegressiveNN(10, 5, [50], param_dims=[1]) >>> p = arn(x, context=y) # 1 parameters of size (100, 10) >>> arn = ConditionalAutoRegressiveNN(10, 5, [50], param_dims=[1, 1]) >>> m, s = arn(x, context=y) # 2 parameters of size (100, 10) >>> arn = ConditionalAutoRegressiveNN(10, 5, [50], param_dims=[1, 5, 3]) >>> a, b, c = arn(x, context=y) # 3 parameters of sizes, (100, 1, 10), (100, 5, 10), (100, 3, 10)
- 参数
input_dim (int) – 输入变量的维度
context_dim (int) – 上下文变量的维度
param_dims (list[int]) – 当 p_n > 1 时,将输出形状为 (p_n, input_dim) 的参数;当 p_n == 1 时,将输出形状为 (input_dim) 的参数。默认为 [1, 1],即输出两个维度为 (input_dim) 的参数,这对于逆自回归流非常有用。
permutation (torch.LongTensor) – 可选的排列,应用于输入并控制自回归分解的顺序。特别是对于单位排列,自回归结构使得雅可比矩阵是上三角的。默认情况下,此排列是随机选择的。
skip_connections (bool) – 是否添加从输入到输出的跳跃连接。
nonlinearity (torch.nn.module) – 前馈网络中使用的非线性激活函数,例如 torch.nn.ReLU()。注意,最终的网络输出没有应用非线性,因此输出是无界的实数。
参考
1. MADE: Masked Autoencoder for Distribution Estimation [arXiv:1502.03509] Mathieu Germain, Karol Gregor, Iain Murray, Hugo Larochelle
2. Inference Networks for Sequential Monte Carlo in Graphical Models [arXiv:1602.06701] Brooks Paige, Frank Wood
- forward(x: torch.Tensor, context: Optional[torch.Tensor] = None) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶
ConditionalDenseNN¶
- class ConditionalDenseNN(input_dim: int, context_dim: int, hidden_dims: List[int], param_dims: List[int] = [1, 1], nonlinearity: torch.nn.modules.module.Module = ReLU())[source]¶
基类:
torch.nn.modules.module.Module
一个简单密集前馈网络的实现,它接受一个上下文变量作为输入,可用于例如一些条件流,如
pyro.distributions.transforms.ConditionalAffineCoupling
。示例用法
>>> input_dim = 10 >>> context_dim = 5 >>> x = torch.rand(100, input_dim) >>> z = torch.rand(100, context_dim) >>> nn = ConditionalDenseNN(input_dim, context_dim, [50], param_dims=[1, input_dim, input_dim]) >>> a, b, c = nn(x, context=z) # parameters of size (100, 1), (100, 10), (100, 10)
- 参数
- forward(x: torch.Tensor, context: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶