gpt4 book ai didi

python - 从 numpy 创建张量时缺少梯度

转载 作者:行者123 更新时间:2023-12-02 02:26:53 26 4
gpt4 key购买 nike

有人可以向我解释一下以下行为吗?

import torch
import numpy as np

z = torch.tensor(np.array([1., 1.]), requires_grad=True).float()

def pre_main(z):
return z * 3.0


x = pre_main(z)
x.backward(torch.tensor([1., 1.]))
print(z.grad)

打印:

None

同时:

import torch
import numpy as np

z = torch.tensor([1., 1.], requires_grad=True).float()

def pre_main(z):
return z * 3.0


x = pre_main(z)
x.backward(torch.tensor([1., 1.]))
print(z.grad)

打印:

tensor([3., 3.])

为什么我的梯度在从 numpy 数组构建时被破坏?我该如何解决这个问题?

最佳答案

你的梯度没有被破坏:grad返回None因为它从未保存在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().

您的 z 就是这种情况张量定义为:

>>> z = torch.tensor(np.array([1., 1.]), requires_grad=True).float()
>>> z.is_leaf
False

比较:

>>> z = torch.tensor([1., 1.], requires_grad=True).float()
>>> z.is_leaf
True

这意味着后者的梯度值将在 z.grad 中.

但请注意:

>>> z = torch.tensor(np.array([1., 1.]), requires_grad=True)
>>> z.is_leaf
True

为了进一步解释这一点:当张量首次初始化时,它是一个叶节点( .is_leaf 返回 True )。一旦您在其上应用函数(此处 .float() 是一个就地运算符),它就不再是叶子,因为它在计算图中有父级。

所以说真的,没有什么可以修复...不过你可以做的是确保渐变保存在z.grad上当向后传递被调用时。因此,第二个问题归结为如何在非叶节点上存储/访问梯度?


现在,如果您想将渐变存储在 .backward() 上称呼。您可以使用 retain_grad() 如警告消息中所述:

z = torch.tensor(np.array([1., 1.]), requires_grad=True).float()
z.retain_grad()

或者,由于我们期望它是叶节点,因此使用 FloatTensor 来解决它转换numpy.arraytorch.Tensor :

z = torch.FloatTensor(np.array([1., 1.]))
z.requires_grad=True

或者,您可以坚持使用 torch.tensor并提供 dtype :

z = torch.tensor(np.array([1., 1.]), dtype=torch.float64, requires_grad=True)

关于python - 从 numpy 创建张量时缺少梯度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65532022/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com