深度学习——pytorch中反向传播,梯度保留,梯度分离,梯度清零,梯度累加等相关问题解析

梯度保留

Q(question):pytorch autograd 非叶子节点的梯度会保留么?
A(answer):
 1. 只有叶子节点的梯度得到保留,中间变量的梯度默认不保留
 2. 叶子节点的值在求梯度前不允许更改	  

示例

>>> a = torch.tensor(2.0, requires_grad=True)
>>> b = torch.tensor(3.0)
>>> c=a*a*5
>>> d=c*c*b
>>> d.backward()
>>> a.grad
tensor(2400.)

注:复制完代码请删去>>>和输出结果再运行,建议手打一遍,这样更能加深理解
默认创建的张量(tensor)为常量,常量无法计算,需要设置requires_grad=True才能计算梯度,所以a,c,d可以计算梯度,b不可以计算梯度。反向传播后,只有叶子节点可以保留梯度,所以这里只有a的梯度会保留,如果需要保留c,d的梯度,需要使用retain_grad()函数
注:大家可以尝试一下计算图的可视化,我这里暂时就不加了,有空补上

>>> a = torch.tensor(2.0, requires_grad=True)
>>> b = torch.tensor(3.0)
>>> c=a*a*5
>>> d=c*c*b
>>> c.retain_grad()
>>> d.retain_grad()
>>> d.backward()
>>> a.grad         #求导后2*b*c*10*a,把c用a*a*5来代,即2*b*a*a*5*10*a为2400
tensor(2400.)     
>>> c.grad        #求导后2*b*c,把c用a*a*5来代,即2*b*a*a*5为120
tensor(120.)    
>>> d.grad
tensor(1.)

注:复制完代码请删去>>>输出结果再运行,建议手打一遍,这样更能加深理解
d.backward() 只能计算一次,因为执行一次 d.backward() 后,计算图的缓冲区已经被释放,再次执行将报如下错误:

RuntimeError: Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). 

如果需要再次使用,则需要在前一次执行backward()时加上retain_graph=True,此时会对之前求到的梯度进行叠加

a = torch.tensor(2.0, requires_grad=True)
b = torch.tensor(3.0)
c=a*a*5
d=c*c*b
c.retain_grad()
d.retain_grad()
d.backward(retain_graph=True)
print(a.grad)
print(c.grad)
print(d.grad)
'''
输出
tensor(2400.)
tensor(120.)
tensor(1.)
'''
d.backward()
print(a.grad)
print(c.grad)
print(d.grad)
'''
输出
tensor(4800.)
tensor(240.)
tensor(2.)
'''

原文链接:
https://blog.csdn.net/liangjiu2009/article/details/106980762
https://blog.csdn.net/go___on/article/details/124294061
https://blog.csdn.net/weixin_43479947/article/details/126989990

梯度清零

在PyTorch中,对模型参数的梯度置0时通常使用两种方式:model.zero_grad()和optimizer.zero_grad()。二者在训练代码都很常见,那么二者的区别在哪里呢?

model.zero_grad()
model.zero_grad()的作用是将所有模型参数的梯度置为0。其源码如下:

for p in self.parameters():
    if p.grad is not None:
        p.grad.detach_()
        p.grad.zero_()

optimizer.zero_grad()
optimizer.zero_grad()的作用是清除所有可训练的torch.Tensor的梯度。其源码如下:

for group in self.param_groups:
    for p in group['params']:
        if p.grad is not None:
            p.grad.detach_()
            p.grad.zero_()

总结

1.因此,当使用optimizer=optim.Optimizer(net.parameters())设置优化器时,此时优化器中的param_groups等于模型中的parameters(),此时,二者是等效的,从二者的源码中也可以看出来。

2.当多个模型使用同一个优化器时,二者是不同的,此时需要根据实际情况选择梯度的清除方式。

梯度分离

detach()函数,返回一个新的tensor,是从当前计算图中分离下来的,但是仍指向原变量的存放位置,其grad_fn=Nonerequires_grad=False,得到的这个tensor永远不需要计算其梯度,不具有梯度grad,即使之后重新将它的requires_grad置为true,它也不会具有梯度grad。

注意:返回的tensor和原始的tensor共享同一内存数据。in-place函数修改会在两个tensor上同时体现(因为它们共享内存数据),此时当要对其调用backward()时可能会导致错误。

原文链接:https://blog.csdn.net/qq_36605433/article/details/120617031

梯度累加

原文链接 https://blog.csdn.net/ltochange/article/details/123629686
原文链接:https://www.cnblogs.com/lart/p/11628696.html

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
反向传播算法是深度学习的核心算法之一,它是用来计算神经网络参数的梯度,并根据梯度更新参数,从而实现模型的训练。 在PyTorch,实现反向传播算法的一般步骤如下: 1. 构建计算图:首先,需要定义神经网络模型,并将输入数据传递给模型进行前向计算,得到模型的输出结果。 2. 计算损失函数:根据模型的输出结果和标签数据,计算损失函数。PyTorch提供了一些常用的损失函数,如交叉熵损失函数、均方误差损失函数等,可以根据具体情况进行选择。 3. 计算梯度:通过调用损失函数的backward()方法,计算损失函数对每个参数的梯度。在计算梯度之前,需要将梯度清零,以避免之前的梯度对当前梯度的影响。 4. 参数更新:根据梯度信息和优化算法,更新模型的参数。PyTorch提供了一些常用的优化算法,如随机梯度下降、Adam等。 下面是一个简单的示例代码,实现了一个简单的全连接神经网络,并使用反向传播算法进行训练: ```python import torch import torch.nn as nn import torch.optim as optim # 定义网络模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(10, 5) self.fc2 = nn.Linear(5, 1) def forward(self, x): x = torch.relu(self.fc1(x)) x = self.fc2(x) return x # 定义输入数据和标签数据 inputs = torch.randn(1, 10) labels = torch.randn(1, 1) # 定义损失函数和优化算法 net = Net() criterion = nn.MSELoss() optimizer = optim.SGD(net.parameters(), lr=0.01) # 计算模型输出和损失函数 outputs = net(inputs) loss = criterion(outputs, labels) # 计算梯度并更新参数 optimizer.zero_grad() loss.backward() optimizer.step() ``` 在上面的代码,首先定义了一个全连接神经网络模型,包含两个线性层。然后,定义了输入数据和标签数据。接着,定义了损失函数和优化算法,并将模型的参数传递给优化器。在每次训练迭代,计算模型的输出结果和损失函数,然后使用反向传播算法计算梯度,并使用优化算法更新模型的参数。 需要注意的是,PyTorch反向传播算法是自动求导的,即不需要手动计算梯度,只需要通过调用backward()方法即可。另外,在每次迭代,需要将梯度清零,否则会累加之前的梯度,导致结果不正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千禧皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值