关键是您不需要从 NN 生成的分布中采样。您只需优化 NN 分布下目标值的似然性。
在 VAE (https://github.com/pytorch/examples/tree/master/vae) 上的官方 PyTorch 示例中有一个示例,尽管是针对多维伯努利分布。
从 PyTorch 0.4 开始,您可以使用 torch.distributions:将分布 distro 与您的 NN 的输出一起实例化,然后优化 -distro.log_prob(target)。
编辑:根据评论中的要求,使用torch.distributions 模块的完整示例。
首先,我们创建一个异方差数据集:
import numpy as np
import torch
X = np.random.uniform(size=300)
Y = X + 0.25*X*np.random.normal(size=X.shape[0])
我们构建了一个简单的模型,它完全能够匹配我们数据的生成过程:
class Model(torch.nn.Module):
def __init__(self):
super().__init__()
self.mean_coeff = torch.nn.Parameter(torch.Tensor([0]))
self.var_coeff = torch.nn.Parameter(torch.Tensor([1]))
def forward(self, x):
return torch.distributions.Normal(self.mean_coeff * x, self.var_coeff * x)
mdl = Model()
optim = torch.optim.SGD(mdl.parameters(), lr=1e-3)
模型的初始化使其始终产生标准正态,这与我们的数据不匹配,因此我们训练(注意这是一个非常愚蠢的批处理训练,但证明您可以为您的批处理输出一组分布一次):
for _ in range(2000): # epochs
dist = mdl(torch.from_numpy(X).float())
obj = -dist.log_prob(torch.from_numpy(Y).float()).mean()
optim.zero_grad()
obj.backward()
optim.step()
最终,学习到的参数应该与我们用来构造 Y 的值相匹配。
print(mdl.mean_coeff, mdl.var_coeff)
# tensor(1.0150) tensor(0.2597)