【机器学习技巧】-训练过程中,loss参数出现NAN怎么解决?解决方案汇总?

一、背景

因为最近在搞毕设,借用交友网站上的yolov5开源代码训练自己的数据集时,第一个epoch就显示各个loss=nan。

而后,近乎绝望的我找到一个玩计算机视觉玩得不错的UP主,一次调试100元, 我欣然同意了,花钱消灾!

今天上午9点约好,他控制我;在20分钟内,他新建了一个虚拟环境,把pytorch由原先的1.9版本重装成1.8版本(仍是GPU类型),接着把其他依赖库安装完后,叫我run一下代码。

非常顺利!截止到我现在写博客总结,已经训练了13轮了,还没有出现loss为nan的情况。

这位大牛告诉我:可能是因为Pytorch在1.9版本中更新了自己的API(特别是涉及到计算方法的部分),损失函数计算模式有所更改,所以用新环境计算出的结果很可能出现NAN的情况。 

参考GITHUB地址:GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch

虽然下面这些情形,我还没遇到,但还是总结一下吧!免得到时候出现NAN,手忙脚乱不知道怎么办。

二、不同情形下不同解决办法

2.1 在不同机器(环境)下运行得到不同结果

如果你跟我一样是使用开源的代码进行训练的,那么强烈建议你新建一个环境,这个环境根据对方提供的environment.yml文件或者requirement.txt文件进行配置。

特别是base部分的依赖库,尽量保持完全一样。

比如我上面用到的YOLOv5,作者给的requirement.txt文件如下:Base部分,应该是最重要的,特别是numpy、torch、OpenCV这几种涉及到算法、计算方式的第三方库。

# pip install -r requirements.txt

# Base ----------------------------------------
matplotlib>=3.2.2
numpy>=1.18.5
opencv-python>=4.1.2
Pillow>=7.1.2
PyYAML>=5.3.1
requests>=2.23.0
scipy>=1.4.1
torch>=1.7.0
torchvision>=0.8.1
tqdm>=4.41.0

# Logging -------------------------------------
tensorboard>=2.4.1
# wandb

# Plotting ------------------------------------
pandas>=1.1.4
seaborn>=0.11.0

# Export --------------------------------------
# coremltools>=4.1  # CoreML export
# onnx>=1.9.0  # ONNX export
# onnx-simplifier>=0.3.6  # ONNX simplifier
# scikit-learn==0.19.2  # CoreML quantization
# tensorflow>=2.4.1  # TFLite export
# tensorflowjs>=3.9.0  # TF.js export
# openvino-dev  # OpenVINO export

# Extras --------------------------------------
# albumentations>=1.0.3
# Cython  # for pycocotools https://github.com/cocodataset/cocoapi/issues/172
# pycocotools>=2.0  # COCO mAP
# roboflow
thop  # FLOPs computation

2.2 epoch=0时,也即一开始训练loss就等于nan

一般是配置问题,比如我在背景部分分享的环境配置问题,当然还有数据集配置问题(eg:label越界、label缺失)。

这种情况下。

如果是环境配置问题,就要重装环境、在朋友电脑上的环境运行一遍。

如果是数据集配置问题,可以尝试换几个模型对同样的数据集进行测试,结果没出错才说明不是数据集的问题。

2.3 epoch>0时,也即训练着训练着就出事了

这种情况下,先建议做以下几点简易的尝试:

  • 增大batch size
  • 减小learning rate

三、简易的尝试不管用,只好逐一调试、排查了!

下面的内容,收集于网络。

训练网络loss出现Nan解决办法 - 知乎

训练深度学习网络时候,出现Nan是什么原因,怎么才能避免? - 知乎

  1. 如果在迭代的100轮以内,出现NaN,一般情况下的原因是因为你的学习率过高,需要降低学习率。可以不断降低学习率直至不出现NaN为止,一般来说低于现有学习率1-10倍即可。
  2. 可能用0作为了除数;可能0或者负数作为自然对数
  3. 在某些涉及指数计算,可能最后算得值为INF(无穷)(比如不做其他处理的softmax中分子分母需要计算exp(x),值过大,最后可能为INF/INF,得到NaN,此时你要确认你使用的softmax中在计算exp(x)做了相关处理(比如减去最大值等等))
  4. 开根号里面要大于0,同时要加个Epsilon,因为开根号的导数,变量在分母上,不加Epsilon导数就成了nan
  5. 训练的时候因为显存不够用半精度的话,会发现如果损失超过半精度最大值就会变成inf,然后面的计算就出现nan
  6. 每一次batch,打印一次loss,检查是否出现梯度爆炸的情况。若有loss=inf,则可以设定一个阈值,梯度超过这个阈值就等于阈值。
  7. 梯度爆炸,注意每个batch前梯度要清零,optimizer.zero_grad()
  • 13
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
当使用Dice Loss时,遇到损失为nan的情况通常是由于梯度爆炸导致的。梯度爆炸是指梯度的值变得非常大,超过了计算机的浮点数表示范围,从而导致损失为nan。 为了解决这个问题,你可以尝试以下几种方法: 1. 梯度剪裁(Gradient Clipping): 这是一种常用的方法,通过限制梯度的范围来避免梯度爆炸。你可以设置一个阈值,如果梯度的范围超过了这个阈值,就将其缩放到合理的范围内。 2. 权重初始化(Weight Initialization): 梯度爆炸的另一个常见原因是权重的初始化不合适。你可以尝试使用一些合适的权重初始化方法,如正态分布或均匀分布,以确保权重的初始值不会过大。 3. 批量归一化(Batch Normalization): 批量归一化是一种常用的正则化技术,可以帮助稳定网络的训练。它通过在每一层的输入上进行归一化,使得输入的分布更加稳定,从而减少了梯度爆炸的可能性。 4. 减小学习率(Reduce Learning Rate): 如果梯度爆炸发生在训练的后期阶段,你可以尝试减小学习率。较小的学习率可以使权重更新的步幅更小,从而减少了梯度爆炸的可能性。 5. 检查网络结构和超参数: 确保网络结构和超参数的设置是正确的。例如,网络的层数是否合适,是否存在过拟合等问题。 综上所述,当遇到Dice Lossnan的情况时,你可以尝试梯度剪裁、权重初始化、批量归一化、减小学习率以及检查网络结构和超参数的设置。这些方法通常可以帮助你解决梯度爆炸的问题。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值