Pytorch反向传播前后梯度相同的问题

问题

Pytorch训练模型时由于需要冻结部分预训练模型的参数,所以想打印下需训练部分梯度是否有变化,但出现了反向传播前后梯度完全相同,但每次迭代的梯度不同的情况。按常理来说,在optimizer.zero_grad()后模型梯度应该清零,然后反向传播再计算梯度。

代码和解决方法

原代码:

''' 前向传播代码'''
if torch.cuda.is_available():
     opt.zero_grad()
     
     grad_before_training = [p.grad for p in model.parameters() if p.requires_grad]
     #print("grad_before_training:", grad_before_training)
     
     loss = torch.square((result["bit"] / frame_pixel_num - target_bitrate) / target_bitrate)[0]
     loss.backward()
     opt.step()

     grad_after_training = [p.grad for p in model.parameters() if p.requires_grad]
     #print("grad_after_training:", grad_after_training) 
     params_updated = False
     #print(torch.sum(grad_before_training[0]), torch.sum(grad_after_training[0]))
     for grad_before, grad_after in zip(grad_before_training, grad_after_training):
         #print(grad_before, grad_after)
         if torch.any(grad_before != grad_after):
             params_updated = True
     if params_updated:
         print("模型参数已更新")
     else:
         print("模型参数未更新")

打印出来结果一直是“模型参数未更新”,原因是grad_before_training与模型参数的梯度是指向同一块内存,loss.backward()后模型参数的梯度更新,grad_before_training也对应更新。
可以在反向传播前后分别打印模型参数的梯度,可以发现反向传播前是0,反向传播后都是新的梯度了。
所以其实这里模型的参数是正常更新的,只是判断更新的代码逻辑出了问题。

解决方法

这里需要创建梯度的副本给grad_before_training:

	grad_before_training = [p.grad.clone() for p in model.parameters() if p.requires_grad]
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值