神经网络¶
模块 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
声明一个由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
- Parameters
init_value (torch.Tensor 或 返回 torch.Tensor 的可调用对象 或 None) – 可以是一个用于急切初始化的张量,一个用于延迟初始化的可调用对象,或者 None 用作装饰器。
约束 (Constraint) – torch 约束,默认为
constraints.real
。event_dim (int) – (可选)与批处理无关的最右侧维度的数量。此维度左侧的维度将被视为批处理维度;如果参数语句位于子采样的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
声明一个由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
- Parameters
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模型或指南中出现多个PyroModule
,它们应该包含在该模型的单个根PyroModule
中。PyroModule
在每次setattr
、getattr
和delattr
事件时,根据属性的嵌套名称与参数存储同步数据:设置
mod.x = x_init
会尝试从参数存储中读取x
。如果在参数存储中找到值,则该值会被复制到mod
中,并且x_init
会被忽略;否则,x_init
会被复制到mod
和参数存储中。读取
mod.x
尝试从参数存储中读取x
。如果在参数存储中找到值,则该值被复制到mod
中;否则,mod
的值被复制到参数存储中。最后,mod
和参数存储就返回的单一值达成一致。删除
del mod.x
会从mod
和参数存储中移除一个值。
注意,两个同名的
PyroModule
都会与全局参数存储同步,因此包含相同的数据。当创建一个PyroModule
,然后删除它,再创建一个同名的模块时,后者将从参数存储中填充前者的数据。为了避免这种持久性,可以在删除PyroModule
之前调用pyro.clear_param_store()
或clear()
。PyroModule
可以直接使用torch.save()
/torch.load()
进行保存和加载,或者间接使用参数存储的save()
/load()
。请注意,torch.load()
会被参数存储中的任何值覆盖,因此在加载之前最好先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()
装饰的方法中被缓存。由于采样语句在Pyro跟踪中只能出现一次,您应确保对采样属性的跟踪访问被包装在.__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))
混合类
PyroModule
可以用作混合类,并支持动态创建混合类的简单语法,例如以下内容是等价的:# 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
混入到输入的Module
的子模块中;因此我们需要 将上述nn.Sequential
的每个子模块进行包装。- Parameters
name (str) – 可选的根 PyroModule 名称。这在另一个 PyroModule 的子 PyroModule 中会被忽略。
- add_module(name: str, module: Optional[torch.nn.modules.module.Module]) None [源代码]¶
向当前模块添加一个子模块。
- 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
和参数存储中移除数据。- Parameters
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)
- Parameters
m (torch.nn.Module) – 一个模块实例。
recurse (bool) – 是否将子模块转换为
PyroModules
。
- class PyroModuleList(modules)[source]¶
基础类:
torch.nn.modules.container.ModuleList
,pyro.nn.module.PyroModule
自回归神经网络¶
- 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)
- Parameters
input_dim (int) – 输入变量的维度
param_dims (list[int]) – 将输出形状转换为维度为 (p_n, input_dim) 的参数,当 p_n > 1 时,以及维度为 (input_dim) 的参数,当 p_n == 1 时。默认值为 [1, 1],即输出两个维度为 (input_dim) 的参数,这对于逆自回归流非常有用。
permutation (torch.LongTensor) – 一个可选的排列,应用于输入并控制自回归分解的顺序。特别是对于恒等排列,自回归结构使得雅可比矩阵是上三角的。默认情况下,这是随机选择的。
skip_connections (bool) – 是否添加从输入到输出的跳跃连接。
非线性 (torch.nn.module) – 在前馈网络中使用的非线性函数,例如 torch.nn.ReLU()。请注意,最终网络输出不应用非线性函数,因此输出是一个无界的实数。
参考:
MADE: 用于分布估计的掩码自编码器 [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)
- Parameters
- forward(x: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶
条件自回归神经网络¶
- 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)
- Parameters
input_dim (int) – 输入变量的维度
context_dim (int) – 上下文变量的维度
param_dims (list[int]) – 将输出形状转换为维度为 (p_n, input_dim) 的参数,当 p_n > 1 时,以及维度为 (input_dim) 的参数,当 p_n == 1 时。默认值为 [1, 1],即输出两个维度为 (input_dim) 的参数,这对于逆自回归流非常有用。
permutation (torch.LongTensor) – 一个可选的排列,应用于输入并控制自回归分解的顺序。特别是对于恒等排列,自回归结构使得雅可比矩阵是上三角的。默认情况下,这是随机选择的。
skip_connections (bool) – 是否添加从输入到输出的跳跃连接。
非线性 (torch.nn.module) – 在前馈网络中使用的非线性函数,例如 torch.nn.ReLU()。请注意,最终网络输出不应用非线性函数,因此输出是一个无界的实数。
参考:
1. MADE: 用于分布估计的掩码自编码器 [arXiv:1502.03509] Mathieu Germain, Karol Gregor, Iain Murray, Hugo Larochelle
2. 图形模型中顺序蒙特卡洛的推理网络 [arXiv:1602.06701] 布鲁克斯·佩奇, 弗兰克·伍德
- forward(x: torch.Tensor, context: Optional[torch.Tensor] = None) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶
条件密集神经网络¶
- 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)
- Parameters
- forward(x: torch.Tensor, context: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor] [source]¶