pytorch训练一段时间突然出现NaN

一、常见原因方法1

https://www.cnblogs.com/bonelee/p/8603750.html

一般来说,出现NaN有以下几种情况:

相信很多人都遇到过训练一个deep model的过程中,loss突然变成了NaN。在这里对这个问题做一个总结。

1.如果在迭代的100轮以内,出现NaN,一般情况下的原因是因为你的学习率过高,需要降低学习率。可以不断降低学习率直至不出现NaN为止,一般来说低于现有学习率1-10倍即可。

2.如果当前的网络是类似于RNN的循环神经网络的话,出现NaN可能是因为梯度爆炸的原因,一个有效的方式是增加“gradient clipping”(梯度截断来解决)

3.可能用0作为了除数;

4.可能0或者负数作为自然对数

5.需要计算loss的数组越界(尤其是自己,自定义了一个新的网络,可能出现这种情况)

6.在某些涉及指数计算,可能最后算得值为INF(无穷)(比如不做其他处理的softmax中分子分母需要计算exp(x),值过大,最后可能为INF/INF,得到NaN,此时你要确认你使用的softmax中在计算exp(x)做了相关处理(比如减去最大值等等))

二、常见原因方法

  1. 梯度爆炸,解决方法:调学习率、梯度剪裁、归一化

     方法:
     1、数据归一化(减均值,除方差,或者加入normalization,例如BN、L2 norm等)
     2、更换参数初始化方法(对于CNN,一般用xavier或者msra的初始化方法);
     3、减小学习率、减小batch size;
     4、加入gradient clipping;
     
     原因:
     1、学习率太大问题导致梯度爆炸:
     原因很简单,学习率较高的情况下,直接影响到每次更新值的程度比较大,走的步伐因此也会大起来。
     如下图,过大的学习率会导致无法顺利地到达最低点,稍有不慎就会跳出可控制区域,此时我们将要面对的就是损失成倍增大(跨量级)。
     这种情况很容易在网络层数比较深的时候出现,所以同样学习率res50可以,res101,会训练NaN
     ([https://blog.youkuaiyun.com/lrt366/article/details/97616926](https://blog.youkuaiyun.com/lrt366/article/details/97616926))
    

原因很简单,学习率较高的情况下,直接影响到每次更新值的程度比较大,走的步伐因此也会大起来。如下图,过大的学习率会导致无法顺利地到达最低点,稍有不慎就会跳出可控制区域,此时我们将要面对的就是损失成倍增大(跨量级)。

  1. 计算loss的时候有log0,可能是初始化的问题,也可能是数据的问题

     loss突然变nan的原因,很可惜并不是这里其他所有答主所说的“因为梯度爆炸”、“lr过大”、“不收敛”等等原因,
     而是因为training sample中出现了脏数据!脏数据的出现导致我的logits计算出了0,0传给  即nan。
     所以我通过设置batch_size = 1,shuffle = False,一步一步地将sample定位到了所有可能的脏数据,删掉。
     期间,删了好几个还依然会loss断崖为nan,不甘心,一直定位一直删。终于tm work out!
     作者:Scofield
     链接:https://www.zhihu.com/question/49346370/answer/309842972
     来源:知乎
    

三、警惕!损失Loss为Nan或者超级大的原因,理由原理充分

https://blog.youkuaiyun.com/lrt366/article/details/97616926
在这里插入图片描述

### 解决 PyTorch 训练中出现的 NaN 梯度问题 #### 设置异常检测机制 为了更方便地定位导致 `NaN` 的具体位置,可以在反向传播阶段启用异常检测功能。通过这种方式,当计算图中的任何操作产生 `NaN` 时,程序将会抛出详细的错误信息并停止执行。 ```python import torch # 开启自动求导的异常侦测 torch.autograd.set_detect_anomaly(True) # 在损失函数反向传播期间捕获异常 with torch.autograd.detect_anomaly(): loss.backward() ``` 此方法有助于快速找到引发 `NaN` 的地方[^4]。 #### 调整超参数——学习率 高学习率可能导致权重更新幅度过大,从而使得梯度变得不稳定甚至趋向于无穷大或零,最终形成 `NaN` 。建议逐步减少初始设定的学习率直到不再观察到此类现象发生: - 尝试将当前学习率下调至原来的十分之一; - 如果仍然存在 `NaN` ,继续降低直至稳定收敛[^3]。 #### 处理特定架构下的特殊状况 对于像 RNN 这样的递归结构来说,“梯度爆炸”是一个常见诱因。为此引入 **Gradient Clipping** 技术能够有效地防止这种情况的发生: ```python nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) ``` 上述代码片段会在每次优化器步进之前裁剪掉超过指定阈值(`max_norm`)的所有梯度绝对值[^2]。 #### 验证输入数据合法性 还需仔细审查用于训练的数据集是否存在非法数值(如除数为零、负对数底等)。确保所有参与运算的操作数都在合理范围内可以避免许多潜在陷阱。 #### 定制化层实现注意事项 若有自定义组件,则需格外留意其内部逻辑是否严谨无误。特别是涉及到复杂数学表达式的部分,务必遵循良好实践以规避溢出风险。例如,在实现 SoftMax 层时应考虑采用移位技巧来预防指数项过大造成的结果失真。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值