【发布时间】:2020-02-24 23:16:24
【问题描述】:
我从多元正态分布中抽取样本,并希望获得它们的对数概率相对于均值的梯度。由于样本很多,这需要一个雅可比行列:
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)
如果您堆叠 grads,则结果是所需的雅可比行列式。是否还有对此的内置和矢量化支持?
相关问题/互联网资源:
这是一个很大的话题,有很多相关的帖子。不过,我认为这个具体问题(关于分布)尚未得到解答:
这个问题与我的基本相同(但没有示例代码和解决方案尝试),遗憾的是没有答案:Pytorch custom function jacobian gradient
这个问题显示了 pytorch 中雅可比的计算,但我认为该解决方案不适用于我的问题:Pytorch most efficient Jacobian/Hessian calculation 它需要以一种似乎与分布不兼容的方式堆叠输入。我无法让它工作。
这个要点有一些 Jacobians 的代码 sn-ps。原则上,它们与上述问题中的方法类似。
【问题讨论】:
-
不要认为它是直截了当的,因为 Torch 实现了反向模式 AD,因此期望输出是标量(在你的情况下它是矢量)。您可以尝试通过复制将 \mu 设为 (10,2),因此 grad 可能会给您正确的 jacobian
-
我同意,使用 pytorch 的 autograd 没有循环可能没有直接的方法来获取雅可比行列式。也就是说,在这种特殊情况下,您的雅可比行列式有一个相对简单的封闭形式,即
grads = torch.mm(samples - mu, torch.inverse(sigma))(您可以使用torch.solve获得更稳定的版本,它不会直接反转)。根据您实际问题的复杂性,也许硬编码雅可比表达式可能是要走的路? -
@jodag,你说得对,这里的雅可比很容易计算。但这是 stackoverflow 的最小可行示例。真正的代码要复杂得多。