【pytorch】梯度爆炸/消失解决办法

every blog every motto: You can do more than you think.

0. 前言

记录一种解决梯度爆炸/消失的解决办法,后续出现类似情况再进行增补

1. 正文

1.1 介绍

1.1.1 背景

训练过程中,出现损失为nan了,知道情况不妙了,如下
在这里插入图片描述

1.1.2 用tensorboard记录下梯度情况

说明: 数据比较大,所以 在每次迭代过程中记录
注意: 每次迭代是耗时的,因为会将损失从GPU传递到CPU,然后再进行记录,我们通过nvidia-smi查看GPU使用情况,发现GPU利用率不高,遂将改为每间隔20次进行保存。

 writer_iter_dir = r'runs/v1/iter'  # 每次迭代保存一次
 if not os.path.join(writer_iter_dir): os.makedirs(writer_iter_dir)
 self.writer_iter = SummaryWriter(writer_iter_dir)
 
for epoch in range(1,50):
	for iter,data in enumerate(dataloader):
        if i % 20 == 0:
           self.writer_iter.add_scalar('Loss/Train_iter', batch_all_loss.item(), i)  # 保存每个batch的损失
           
           for name, param in self.net.named_parameters():
               self.writer_iter.add_histogram('batch_' + name + '_param', param, i)  # 记录参数
               self.writer_iter.add_histogram('batch_' + name + '_grad', param.grad, i)  # 记录梯度

1.1.3 查看损失和梯度

损失如下:
在这里插入图片描述

如下图所示,
我们查看的是每次迭代的记录(我们也进行了每个epoch的保存,代码和上面类似,不赘述)
我们看到当前的卷积块:stage_1_decoding.double_conv.0,其权重梯度 在第1次(下图显示的迭代次数为0)为2.05e4,后续迭代也是类似
在这里插入图片描述
我们再看下权重,如下图所示
权重也是比较大,第160次迭代为2.93e3,且为均匀分布
在这里插入图片描述

1.2 解决办法

梯度爆炸可能和我们使用Pytorch中卷积的层的权重有关,其中,默认权重为均匀分布,如下图所示
pytorch,卷积层链接
在这里插入图片描述
我们对其进行修改为正态分布,
说明: 模型要先实例化

 # 权重初始化
 for m in self.net.modules():
     if isinstance(m, nn.Conv2d):
         init.xavier_normal(m.weight.data)

修改后的损失,
在这里插入图片描述

修改后的权重如下
在这里插入图片描述
梯度如下,
在这里插入图片描述

参考文献

[1] https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html?highlight=conv2d#torch.nn.Conv2d
[2] https://tensorflow.google.cn/versions/r2.0/api_docs/python/tf/keras/layers/Conv2D
[3] https://blog.csdn.net/u010368556/article/details/81148267
[4] https://blog.csdn.net/qq_25737169/article/details/78847691
[5] https://www.cnblogs.com/zhangxiann/p/13617142.html
[6] https://www.cnblogs.com/zhangxiann/p/13617142.html
[7] https://blog.csdn.net/u010099080/article/details/77426577
[8] https://zhuanlan.zhihu.com/p/56253634
[9] https://www.cnblogs.com/my-love-is-python/p/11725664.html

PyTorch 中的梯度爆炸是指在反向传播过程中,梯度值变得非常大,导致权重更新的变化非常大,从而无法收敛。以下是几种可以解决梯度爆炸的方法: 1. 梯度裁剪(Gradient Clipping):梯度裁剪是一种简单但有效的方法,通过对梯度进行限制,使其不超过一个阈值。在 PyTorch 中,可以使用 `torch.nn.utils.clip_grad_norm_` 函数来实现梯度裁剪。该函数将所有参数的梯度连接成单个向量,然后计算该向量的范数,并将梯度除以该范数(如果小于阈值)或者将梯度除以阈值(如果大于阈值),从而限制梯度的大小。 2. 使用更小的学习率:梯度爆炸通常发生在学习率过大的情况下,因此可以尝试减小学习率,这样梯度变化就会更加平缓。 3. 权重初始化:权重的初始值可能会影响模型的训练效果。如果权重的初始值过大,那么在反向传播过程中,梯度也会变得非常大。因此,可以尝试使用更小的初始权重来避免梯度爆炸。 4. 使用 Batch Normalization:Batch Normalization 是一种常用的正则化方法,可以通过规范化每个批次的输入来减少内部协变量偏移(Internal Covariate Shift)。Batch Normalization 已经得到广泛应用,而且可以防止梯度爆炸。 5. 简化模型:模型太复杂可能会导致梯度爆炸,因此可以尝试简化模型,例如减少模型中的层数或者减少每层的神经元数量。 6. 使用更好的优化器:优化器的选择也会影响梯度的变化。例如,Adam 优化器可以自适应地调整学习率和梯度的大小,从而可以避免梯度爆炸。 需要注意的是,梯度爆炸的原因可能有很多,不同的模型或者数据集可能需要采用不同的方法来解决梯度爆炸问题。因此,需要根据具体情况进行调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

胡侃有料

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

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

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

打赏作者

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

抵扣说明:

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

余额充值