考虑以下代码:
x = torch.tensor(2.0, requires_grad=True)
y = torch.square(x)
grad = autograd.grad(y, x)
x = x + grad[0]
y = torch.square(x)
grad2 = autograd.grad(y, x)
首先,我们有∇(x^2)=2x
。据我所知,grad2=∇((x + ∇(x^2))^2)=∇((x+2x)^2)=∇((3x)^2)=9∇x^2=18x
。不出所料,grad=4.0=2x
,但grad2=12.0=6x
,我不明白它是从哪里来的。感觉3
来自我的表达式,但它不是平方的,2
来自传统的导数。有人能帮我理解为什么会发生这种事吗?此外,存储梯度的计算图可以追溯到多远?
具体来说,我是从元学习的角度出发的,其中人们对计算以下形式的量∇ L(theta - alpha * ∇ L(theta))=(1 + ∇^2 L(theta)) ∇L(theta - alpha * ∇ L(theta)
感兴趣(这里的导数是关于theta
的(。因此,我们称之为A
的计算包括一个二阶导数。计算与下面的∇_{theta - alpha ∇ L(theta)}L(theta - alpha * ∇ L(theta))=∇_beta L(beta)
非常不同,我将其称为B
。
希望我能清楚地看到我的片段与我在第二段中描述的内容之间的关系。我的总体问题是:pytorch在什么情况下使用autograd.grad
实现计算A
与计算B
?如果能对autograd
如何处理此特定案例的技术详细信息做出任何解释,我将不胜感激。
PD。我遵循的原始代码让我怀疑这是在这里;特别是第69到106行,以及随后的第193行,当它们使用autograd.grad
时。因为代码更不清楚,因为他们做了很多model.clone()
等等
如果这个问题有任何不清楚的地方,请告诉我。
我做了一些更改:
- 我不确定
torch.rand(2.0)
应该做什么。根据文本,我只是将其设置为2 - 添加了一个中间变量
z
,这样我们就可以计算原始变量的梯度w.r.t。您的被覆盖 - 设置
create_graph=True
以计算更高阶梯度。看见https://pytorch.org/docs/stable/generated/torch.autograd.grad.html
import torch
from torch import autograd
x = torch.ones(1, requires_grad=True)*2
y = torch.square(x)
grad = autograd.grad(y, x, create_graph=True)
z = x + grad[0]
y = torch.square(z)
grad2 = autograd.grad(y, x)
# yours is more like autograd.grad(y, z)
print(x)
print(grad)
print(grad2)