Pytorch最有效的Jacobian / Hessian计算

时间:2019-06-06 15:18:03

标签: python deep-learning pytorch linear-algebra calculus

我正在寻找通过Pytorch获得函数的雅可比行列的最有效方法,到目前为止,已经提出了以下解决方案:

def func(X):
    return torch.stack((
                     X.pow(2).sum(1),
                     X.pow(3).sum(1),
                     X.pow(4).sum(1)
                      ),1)  

X = Variable(torch.ones(1,int(1e5))*2.00094, requires_grad=True).cuda()

                                # Solution 1:
t = time()
Y = func(X)
J = torch.zeros(3, int(1e5))
for i in range(3):
    J[i] = grad(Y[0][i], X, create_graph=True, retain_graph=True, allow_unused=True)[0]
print(time()-t)
Output: 0.002 s

                                # Solution 2:
def Jacobian(f,X):
    X_batch = Variable(X.repeat(3,1), requires_grad=True)
    f(X_batch).backward(torch.eye(3).cuda(),  retain_graph=True)
    return X_batch.grad

t = time()
J2 = Jacobian(func,X)
print(time()-t)
Output: 0.001 s

由于在第一种解决方案中使用循环似乎与第二种解决方案之间并没有太大差异,所以我想问一问,是否仍然有一种更快的方法可以在pytorch中计算Jacobian。

然后,我的另一个问题是关于哪种最有效的方法来计算Hessian。

最后,有人知道在TensorFlow中是否可以更轻松或更有效地完成这样的事情?

2 个答案:

答案 0 :(得分:1)

最有效的方法可能是使用 PyTorch 自己的内置函数:

torch.autograd.functional.jacobian(func, x)
torch.autograd.functional.hessian(func, x)

答案 1 :(得分:0)

我有一个类似的问题,可以通过手动定义Jacobian(手动计算导数)来解决。对于我的问题,这是可行的,但我可以想象并非总是如此。与第二种解决方案相比,计算时间加快了我的计算机(cpu)上的某些因素。但是,我不能在第一个解决方案中使用grad(...)函数。

# Solution 2
def Jacobian(f,X):
    X_batch = Variable(X.repeat(3,1), requires_grad=True)
    f(X_batch).backward(torch.eye(3).cuda(),  retain_graph=True)
    return X_batch.grad

%timeit Jacobian(func,X)
11.7 ms ± 130 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# Solution 3
def J_func(X):
    return torch.stack(( 
                 2*X,
                 3*X.pow(2),
                 4*X.pow(3)
                  ),1)

%timeit J_func(X)
539 µs ± 24.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)