PyTorch-按顺序在两个不同的函数上调用 backward() 会第二次给出意外输出
PyTorch- call to backward() on two different functions in sequence gives unexpected output second time
我试图区分基于相同输入 x[=29] 的两个函数 z 和 y =].在这样做的同时,我 运行 y.backward()
和 z.backward()
。根据我的理解,我在对输入进行任何操作之前创建了两个函数,因此 y 和 z 应该是独立的并给出独立的结果分化。
但是,第二次调用 backward() 的输出给出了错误的输出。它可以被称为 y.backward()
然后 z.backward()
。在这种情况下,z.backward() 给出 14 而不是 12 作为输出。如果我 运行 z.backward()
然后 y.backward()
,y.backward()
给出 14 作为输出。在这两种情况下,只有第一个输出是正确的。我不明白第二次给14是怎么回事。
import torch
x = torch.tensor(2.0, requires_grad=True)
y = 2 * x + 3
z = x**3 + 1
y.backward()
print('grad attribute of the tensor::',x.grad)
z.backward()
print('grad attribute of the tensor::',x.grad)
输出:
grad attribute of the tensor:: tensor(2.)
grad attribute of the tensor:: tensor(14.)
backward()
不覆盖tensor grad属性;它 积累 它们。如果您不将反向传播之间的梯度归零,则生成的梯度将是每个反向传播的梯度之和。之所以这样实现,是为了更好地支持循环神经网络。
将梯度归零的最传统方法是调用torch.optim.Optimizer.zero_grad()
;这将使在构造时传递给优化器的所有参数的梯度归零。当您只是将渐变用于优化器步骤时,这很有效。还有 torch.nn.Module.zero_grad()
,它将模块的参数归零(我相信它是递归的,所以它也应该将 sub-modules' 参数归零,等等)。
还要注意,如果需要复用中间结果(non-leaf张量的梯度),那么在调用backward()
时需要传递retain_graph=True
;在使用递归神经网络时通常就是这种情况。否则,PyTorch 将释放它们以节省内存。
我试图区分基于相同输入 x[=29] 的两个函数 z 和 y =].在这样做的同时,我 运行 y.backward()
和 z.backward()
。根据我的理解,我在对输入进行任何操作之前创建了两个函数,因此 y 和 z 应该是独立的并给出独立的结果分化。
但是,第二次调用 backward() 的输出给出了错误的输出。它可以被称为 y.backward()
然后 z.backward()
。在这种情况下,z.backward() 给出 14 而不是 12 作为输出。如果我 运行 z.backward()
然后 y.backward()
,y.backward()
给出 14 作为输出。在这两种情况下,只有第一个输出是正确的。我不明白第二次给14是怎么回事。
import torch
x = torch.tensor(2.0, requires_grad=True)
y = 2 * x + 3
z = x**3 + 1
y.backward()
print('grad attribute of the tensor::',x.grad)
z.backward()
print('grad attribute of the tensor::',x.grad)
输出:
grad attribute of the tensor:: tensor(2.)
grad attribute of the tensor:: tensor(14.)
backward()
不覆盖tensor grad属性;它 积累 它们。如果您不将反向传播之间的梯度归零,则生成的梯度将是每个反向传播的梯度之和。之所以这样实现,是为了更好地支持循环神经网络。
将梯度归零的最传统方法是调用torch.optim.Optimizer.zero_grad()
;这将使在构造时传递给优化器的所有参数的梯度归零。当您只是将渐变用于优化器步骤时,这很有效。还有 torch.nn.Module.zero_grad()
,它将模块的参数归零(我相信它是递归的,所以它也应该将 sub-modules' 参数归零,等等)。
还要注意,如果需要复用中间结果(non-leaf张量的梯度),那么在调用backward()
时需要传递retain_graph=True
;在使用递归神经网络时通常就是这种情况。否则,PyTorch 将释放它们以节省内存。