Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Neural network 为什么我们需要显式调用zero_grad()?_Neural Network_Deep Learning_Pytorch_Gradient Descent - Fatal编程技术网

Neural network 为什么我们需要显式调用zero_grad()?

Neural network 为什么我们需要显式调用zero_grad()?,neural-network,deep-learning,pytorch,gradient-descent,Neural Network,Deep Learning,Pytorch,Gradient Descent,为什么我们需要显式地将PyTorch中的梯度归零?为什么调用loss.backward()时不能将渐变归零?将梯度保留在图形上,并要求用户显式地将梯度归零,这适用于什么情况?我们显式地需要调用zero\u grad(),因为在loss.backward()(计算梯度时)之后,我们需要使用optimizer.step()来进行梯度下降。更具体地说,渐变不会自动归零,因为这两个操作,loss.backward()和optimizer.step()是分开的,并且optimizer.step()需要刚刚

为什么我们需要显式地将PyTorch中的梯度归零?为什么调用
loss.backward()
时不能将渐变归零?将梯度保留在图形上,并要求用户显式地将梯度归零,这适用于什么情况?

我们显式地需要调用
zero\u grad()
,因为在
loss.backward()
(计算梯度时)之后,我们需要使用
optimizer.step()
来进行梯度下降。更具体地说,渐变不会自动归零,因为这两个操作,
loss.backward()
optimizer.step()
是分开的,并且
optimizer.step()
需要刚刚计算的渐变


此外,有时我们需要在一些批次之间累积梯度;要做到这一点,我们只需多次向后调用
并进行一次优化。

我有一个PyTorch中当前设置的用例

如果一个人使用的是在每一步都进行预测的递归神经网络(RNN),那么他可能希望有一个超参数,允许他在时间上累积梯度。不必在每个时间步将梯度归零,就可以以有趣而新颖的方式使用时间反向传播(BPTT)


如果您想了解有关BPTT或RNN的更多信息,请参阅文章或。

在调用
之前保留梯度。如果您想在多个批次之间累积梯度(如其他人所述),步骤()
非常有用


如果您想为SGD实现动量,那么在调用
.step()
之后,它也很有用,其他各种方法可能取决于上一次更新的梯度值。

PyTorch中有一个循环:

  • 当我们从输入中获得输出或
    y\u hat
    时向前
  • 计算损失,其中
    loss=loss\u fn(y\u hat,y)
  • loss.backward
    当我们计算梯度时
  • 优化程序。更新参数时的步骤
或在代码中:

for mb in range(10): # 10 mini batches
    y_pred = model(x)
    loss = loss_fn(y_pred, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
如果我们不在
优化器.step
之后清除梯度,这是适当的步骤,或者在下一个
backward()之前,梯度将累积。
下面是一个显示累积的示例:

import torch
w = torch.rand(5)
w.requires_grad_()
print(w) 
s = w.sum() 
s.backward()
print(w.grad) # tensor([1., 1., 1., 1., 1.])
s.backward()
print(w.grad) # tensor([2., 2., 2., 2., 2.])
s.backward()
print(w.grad) # tensor([3., 3., 3., 3., 3.])
s.backward()
print(w.grad) # tensor([4., 4., 4., 4., 4.])
没有任何方法指定此项

torch.autograd.backward(张量,梯度张量=None,保留图=None,创建图=False,梯度变量=None)

从所有可以指定的选项中,无法手动将渐变归零。如前一个迷你示例中所示:

w.grad.zero_()

关于每次使用
backward()
(显然是以前的梯度)进行
zero_grad()
,并保持梯度,有一些讨论,但这从未出现过。这个答案需要更清楚一些。也许一个例子会有所帮助。下面是它将更新的变量的示例+梯度(即模型的可学习+权重)的解释。这是因为在默认情况下,每当调用.backward()+#时,渐变都会被+#累积在缓冲区中(即,不会被覆盖)。有关详细信息,请查看torch.autograd.backward的文档。实际上,您提到了“minibatch”(或“batch subpartition”)与“batch”——在这种情况下,累加在前馈网络(不仅仅是RNN)中很有用。当我们需要一个更大的批量进行优化,但有物理限制(例如GPU内存)来增加样本数时。您能举一个例子说明我们需要累积梯度吗?@RedFloyd,以防您想要有效地训练一个大批量(想象64),但您的GPU同时只能容纳32个示例。您需要通过两个步骤累积渐变,并且每两个步骤只调用一次
optimizer.step()