在 pytorch 中的一个简单测试中,我想查看非叶张量中的 grad,因此我使用retain_grad():
import torch
a = torch.tensor([1.], requires_grad=True)
y = torch.zeros((10))
gt = torch.zeros((10))
y[0] = a
y[1] = y[0] * 2
y.retain_grad()
loss = torch.sum((y-gt) ** 2)
loss.backward()
print(y.grad)
Run Code Online (Sandbox Code Playgroud)
它给了我一个正常的输出:
tensor([2., 4., 0., 0., 0., 0., 0., 0., 0., 0.])
Run Code Online (Sandbox Code Playgroud)
但是当我在 y[1] 之前和 y[0] 分配之后使用保留 grad() 时:
import torch
a = torch.tensor([1.], requires_grad=True)
y = torch.zeros((10))
gt = torch.zeros((10))
y[0] = a
y.retain_grad()
y[1] = y[0] * 2
loss = torch.sum((y-gt) ** 2)
loss.backward()
print(y.grad)
Run Code Online (Sandbox Code Playgroud)
现在输出更改为:
tensor([10., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
Run Code Online (Sandbox Code Playgroud)
我根本无法理解这个结果。
好吧,发生的事情真的很奇怪。
本质.retain_grad()上是将任何非叶张量转换为叶张量,使其包含一个.grad属性(因为默认情况下,pytorch 仅计算叶张量的梯度)。
因此,在您的第一个示例中,在调用 后y.retain_grad(),它基本上转换y为具有可访问属性的叶张量.grad。
但是,在第二个示例中,您最初将整个y张量转换为叶张量;然后,您(y[1]) 在叶张量中创建了一个非叶张量(y),这就是造成混乱的原因。
y = torch.zeros((10)) # y is a non-leaf tensor
y[0] = a # y[0] is a non-leaf tensor
y.retain_grad() # y is a leaf tensor (including y[1])
y[1] = y[0] * 2 # y[1] is a non-leaf tensor, BUT y[0], y[2], y[3], ..., y[9] are all leaf tensors!
Run Code Online (Sandbox Code Playgroud)
令人困惑的部分是:
y[1] 调用后现在y.retain_grad() 是一个带有.grad属性的叶张量。然而,计算y[1] 之后(y[1] = y[0] * 2)现在不是一个带有.grad属性的叶张量;它现在被视为新的非叶变量/张量。
因此,当调用 时, wrtloss.backward()的链式规则,特别是查看wrt 叶子的链式规则现在看起来像这样:lossylossy[1]
| 归档时间: |
|
| 查看次数: |
6014 次 |
| 最近记录: |