import torch
import torch.optim as optim
import torch.nn as nn
input = torch.tensor([1.,2.], requires_grad=True)
sigmoid = nn.Sigmoid()
interm = sigmoid(input)
optimizer = optim.SGD([input], lr=1, momentum=0.9)
for epoch in range(5):
optimizer.zero_grad()
loss = torch.linalg.vector_norm(interm - torch.tensor([2.,2.]))
print(epoch, loss, input, interm)
loss.backward(retain_graph=True)
optimizer.step()
print(interm.grad)
因此,我创建了这个简化的示例,其中输入进入 sigmoid 作为中间激活函数。
我试图找到导致interm = [2.,2.]的输入
但梯度没有通过。有人知道为什么吗?
计算叶张量的梯度。在您的示例中,
input
是叶张量,而interm
不是。当您尝试访问 时
interm.grad
,您应该收到以下错误消息:UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at aten/src/ATen/core/TensorBody.h:486.)
这是因为梯度被传播回叶张量
input
,而不是interm
。interm.retain_grad()
如果您想获取变量的等级,您可以添加interm
。但是,即使您这样做了,您的示例中也不会导致 的值
interm
发生变化。每个优化器步骤都会更改input
值,但这不会导致interm
重新计算。如果要interm
更新,则需要在每次迭代时使用新input
值重新计算。IE:您正在尝试做的事情还存在一个根本问题。你说你想要
input
那个结果interm = [2., 2.]
。然而,你正在计算interm = sigmoid(input)
。sigmoid 函数的边界为(0, 1)
. 不存在input
会导致的值interm = [2., 2.]
,因为2
超出了 sigmoid 函数的范围。如果无限期地运行优化循环,您将得到input = [inf, inf]
和interm = [1., 1.]
。