如何使用pytorch获取jacobian的多元正态分布的对数概率

时间:2019-10-29 16:56:14

标签: python pytorch

我从多元正态分布中提取了样本,并希望获得其对数概率相对于均值的梯度。由于样本很多,因此需要一个雅可比行列式:

import torch

mu = torch.ones((2,), requires_grad=True)
sigma = torch.eye(2)
dist = torch.distributions.multivariate_normal.MultivariateNormal(mu, sigma)

num_samples=10
samples = dist.sample((num_samples,))
logprobs = dist.log_prob(samples)

现在,我想获得logprobs中每个条目相对于mu中每个条目的派生。

一个简单的解决方案是python循环:

grads = []
for logprob in logprobs:
    grad = torch.autograd.grad(logprob, mu, retain_graph=True)
    grads.append(grad)

如果堆叠毕业,则结果是所需的雅可比行列式。是否还对此提供了内置的矢量化支持?

相关问题/互联网资源:

这是一个巨大的话题,有很多相关文章。不过,我认为这个特定问题(关于分布)尚未得到答案:

  • 此问题与我的问题基本相同(但没有示例代码和解决方案尝试),遗憾的是未得到回答:Pytorch custom function jacobian gradient

  • 此问题显示了在pytorch中计算jacobian的计算,但是我认为该解决方案不适用于我的问题:Pytorch most efficient Jacobian/Hessian calculation它要求以看起来与发行版不兼容的方式堆叠输入。我无法使其正常工作。

  • 此要点有一些针对Jacobian的代码段。原则上讲,它们类似于上面问题中的方法。

1 个答案:

答案 0 :(得分:1)

PyTorch 1.5.1引入了torch.autograd.functional.jacobian函数。这将计算函数w.r.t的雅可比行列式。输入张量。由于jacobian需要将python函数作为第一个参数,因此使用它需要进行一些代码重构。

import torch

torch.manual_seed(0)    # for repeatable results

mu = torch.ones((2,), requires_grad=True)
sigma = torch.eye(2)
num_samples = 10

def f(mu):
    dist = torch.distributions.multivariate_normal.MultivariateNormal(mu, sigma)
    samples = dist.sample((num_samples,))
    logprobs = dist.log_prob(samples)
    return logprobs

grads = torch.autograd.functional.jacobian(f, mu)

print(grads)
tensor([[-1.1258, -1.1524],
        [-0.2506, -0.4339],
        [ 0.5988, -1.5551],
        [-0.3414,  1.8530],
        [ 0.4681, -0.1577],
        [ 1.4437,  0.2660],
        [ 1.3894,  1.5863],
        [ 0.9463, -0.8437],
        [ 0.9318,  1.2590],
        [ 2.0050,  0.0537]])