神经网络

模块 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 的别名

event_dim: Optional[int]

字段编号 2 的别名

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 效果修改。属性可以使用辅助函数 PyroParamPyroSample 设置,方法可以使用 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 在每次 setattrgetattrdelattr 事件时,根据属性的嵌套名称与 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]

向当前模块添加一个子模块。

named_pyro_params(prefix: str = '', recurse: bool = True) Iterator[Tuple[str, torch.nn.parameter.Parameter]][source]

返回一个遍历 PyroModule 参数的迭代器,同时产生参数的名称和参数本身。

参数
  • prefix (str) – 前缀,添加到所有参数名称之前。

  • recurse (bool) – 如果为 True,则产生此模块和所有子模块的参数。否则,只产生此模块的直接成员参数。

返回

一个生成器,产生包含名称和参数的元组。

training: bool
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) – 输入变量的维度

  • hidden_dims (list[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]
training: bool

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)
参数
  • input_dim (int) – 输入的维度

  • hidden_dims (list[int]) – 每层的隐藏单元维度

  • param_dims (list[int]) – 当 p_n > 1 时,将输出形状为 (p_n,) 的参数;当 p_n == 1 时,将输出形状为 () 的参数。默认为 [1, 1],即输出两个维度为 () 的参数。

  • nonlinearity (torch.nn.module) – 前馈网络中使用的非线性激活函数,例如 torch.nn.ReLU()。注意,最终的网络输出没有应用非线性,因此输出是无界的实数。

forward(x: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor][source]
training: bool

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) – 上下文变量的维度

  • hidden_dims (list[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]
get_permutation() torch.LongTensor[source]

获取应用于输入的排列(默认情况下是随机选择的)

training: bool

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)
参数
  • input_dim (int) – 输入的维度

  • context_dim (int) – 上下文变量的维度

  • hidden_dims (list[int]) – 每层的隐藏单元维度

  • param_dims (list[int]) – 当 p_n > 1 时,将输出形状为 (p_n,) 的参数;当 p_n == 1 时,将输出形状为 () 的参数。默认为 [1, 1],即输出两个维度为 () 的参数。

  • nonlinearity (torch.nn.Module) – 前馈网络中使用的非线性激活函数,例如 torch.nn.ReLU()。注意,最终的网络输出没有应用非线性,因此输出是无界的实数。

forward(x: torch.Tensor, context: torch.Tensor) Union[Sequence[torch.Tensor], torch.Tensor][source]
training: bool