警惕!损失Loss为Nan或者超级大的原因 |
您所在的位置:网站首页 › 服务器太热会爆炸吗 › 警惕!损失Loss为Nan或者超级大的原因 |
点击小眼睛开启蜘蛛网特效 警惕!损失Loss为Nan或者超级大的原因 Oldpan 2018年11月7日 11条评论 50,904次阅读 83人点赞 ![]() 训练或者预测过程中经常会遇到训练损失值或者验证损失值不正常、无穷大、或者直接nan的情况: 遇到这样的现象,通常有以下几个原因导致: 梯度爆炸造成Loss爆炸原因很简单,学习率较高的情况下,直接影响到每次更新值的程度比较大,走的步伐因此也会大起来。如下图,过大的学习率会导致无法顺利地到达最低点,稍有不慎就会跳出可控制区域,此时我们将要面对的就是损失成倍增大(跨量级)。 另外,这种情况很容易在网络层数比较深的时候出现,借用gluon的一段话:
这就是典型的梯度爆炸,解决方法也很简单,降低初始的学习率,并设置学习率衰减。 检查输入数据和输出数据通常我们都会保证输入的数据是否正确(这个要是不能保证那么后续也就没必要继续了..)。一般输入不正确的话可以立马观察出来。 有两种情况可能并不是那么容易检测到: 数据比较多,99%的数据是对的,但有1%的数据不正常,或者损坏,在训练过程中这些数据往往会造成nan或者inf,这时候需要仔细挑选自己的数据,关于如何挑选数据(https://oldpan.me/archives/how-to-use-tricks-to-train-network)。 训练过程中跳出了错误的数据,这是需要在IDE或者通过其他途径对运行中的程序进行分析。这时我们要注意的是在训练过程中的输入和输出是否正确:
在神经网络中,很有可能在前几层的输入是正确的,但是到了某一层的时候输出就会变成nan或者inf(其中-inf代表负无穷,而nan代表不存在的数),这个时候就需要通过debug去一一检查。 当然我们可以在自己代码中添加检测函数。 例如在Pytorch框架中我们可以使用torch.autograd.tect_anomaly类来监测训练或者预测过程中遇到的隐晦的问题: >>> import torch >>> from torch import autograd >>> class MyFunc(autograd.Function): ... @staticmethod ... def forward(ctx, inp): ... return inp.clone() ... @staticmethod ... def backward(ctx, gO): ... # Error during the backward pass ... raise RuntimeError("Some error in backward") ... return gO.clone() >>> def run_fn(a): ... out = MyFunc.apply(a) ... return out.sum() >>> inp = torch.rand(10, 10, requires_grad=True) >>> out = run_fn(inp) >>> out.backward() Traceback (most recent call last): File "", line 1, in File "/your/pytorch/install/torch/tensor.py", line 93, in backward torch.autograd.backward(self, gradient, retain_graph, create_graph) File "/your/pytorch/install/torch/autograd/__init__.py", line 90, in backward allow_unreachable=True) # allow_unreachable flag File "/your/pytorch/install/torch/autograd/function.py", line 76, in apply return self._forward_cls.backward(self, *args) File "", line 8, in backward RuntimeError: Some error in backward >>> with autograd.detect_anomaly(): ... inp = torch.rand(10, 10, requires_grad=True) ... out = run_fn(inp) ... out.backward() Traceback of forward call that caused the error: File "tmp.py", line 53, in out = run_fn(inp) File "tmp.py", line 44, in run_fn out = MyFunc.apply(a) Traceback (most recent call last): File "", line 4, in File "/your/pytorch/install/torch/tensor.py", line 93, in backward torch.autograd.backward(self, gradient, retain_graph, create_graph) File "/your/pytorch/install/torch/autograd/__init__.py", line 90, in backward allow_unreachable=True) # allow_unreachable flag File "/your/pytorch/install/torch/autograd/function.py", line 76, in apply return self._forward_cls.backward(self, *args) File "", line 8, in backward RuntimeError: Some error in backward 损失函数可能不正确损失函数也是有可能导致输出nan,尤其是在我们自己设计损失函数的时候。 损失函数应该考虑到是否可以正常地backward。 其次对输入的Tensor是否进行了类型转化,保证计算中保持同一类型。 最后考虑在除数中加入微小的常数保证计算稳定性。 batchNorm可能捣鬼如果你的网络中batchNorm层很多,而且充当比较重要的角色,那么可以适当地检查一下Tensor在输入Batchnorm层后有没有可能变为nan,如果恰好发生这种情况,batchNorm层中的移动均值(running_mean)和移动方差(running_var)也很有可能都是nan,而且这种情况很有可能发生在预测阶段。 这种情况通过发生在训练集和验证集是两个截然不同的分布的时候,这是在训练集中学习到的均值和方法在验证集中是没有作用反而会捣乱。或者在一个神经网络中存在两种结构不同的阵营:典型的是Unet,当在自定义Unet的时候,编码网络和解码网络如果是两个结构存在较大差异的网络,那么在编码阶段学习到的分布在解码阶段就会出现问题。 举个真实的例子:Unet + resnet34 表现正常,但是使用Unet + resnext50 则造成损失爆炸(将解码阶段的batchnorm层失效后表现正常)。 当然上述现象出现的原因大部分在当我们使用model.eval()(Pytorch)之后发生。如果你在预测阶段也将模型model设置为model.train(True),那么问题可能就不会出现: 解决方式: 或者设置Batchnorm中的参数track_running_stats=False使移动均值和移动方差不起作用: 相关的问题: https://github.com/BVLC/caffe/pull/5136 采用stride大于kernel size的池化层在卷积层的卷积步伐大于卷积核大小的时候,有可能产生nan: 比如: layer { name: "faulty_pooling" type: "Pooling" bottom: "x" top: "y" pooling_param { pool: AVE stride: 5 kernel: 3 } } 你的Shuffle设置有没有乱动Suffle即洗牌的意思,如果我们在数据加载阶段将Shuffle参数设置在True,那么在神经网络的读取数据的时候,将会打乱顺序去读取,也就是不按照数据的排列顺序去读取。 一般我们是在训练阶段开启shuffle而在预测阶段关闭shuffle,训练阶段在进行每个epoch的时候开启shuffle可以使数据充分地被随机过一遍(类似于我们烤鱼,我们选择是频繁将鱼上下翻面(shuffle)或者只翻一次面,每次烤很长时间),这样训练的鲁棒性比不shuffle稍高一些。 但是假如我们使用了batch_norm层,并且数据的分布极不规律(使用shuflle和不使用shuffle读取的数据顺序的信息分布完全不同),那么在训练阶段训练好的模型(使用shuffle),在预测阶段使用的时候(不使用shuffle),由于数据分布的不同,也是有可能导致batch_norm层出现nan,从而导致不正常的损失函数出现。 在GPU上和CPU上表现并不同还有种可能的情况,也是没办法的情况,该深度学习框架存在Bug –> 在GPU上运行损失爆炸,但移动到CPU上可能就没有问题,这时候该怎么办么?查找关键原因,赶紧去提个Issue吧~ 参考资料: https://discuss.pytorch.org/t/model-breaks-in-evaluation-mode/2190 https://discuss.pytorch.org/t/model-eval-gives-incorrect-loss-for-model-with-batchnorm-layers/7561/19 https://stackoverflow.com/questions/33962226/common-causes-of-NaNs-during-training 点赞 分享打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮 故障问题 机器学习 深度学习 算法 本篇文章采用 署名-非商业性使用-禁止演绎 4.0 国际 进行许可 转载请务必注明来源: https://oldpan.me/archives/careful-train-loss-nan-inf关注Oldpan博客微信公众号,你最需要的及时推送给你。 ![]() 现在我没有办法了,只能试试继续训练到loss值降不下去,然后再固定bn层继续训练 O Oldpan说道: 2021年3月28日 下午11:11呃,现在还是会出现nan么?学习率有没有调小点 我 我的红呢说道: 2021年3月29日 下午5:39还是会出现,我是修复方向的代码,我一步步测试,应该是mask出了问题,还在验证 我 我的红呢说道: 2021年3月18日 下午11:26找了好久终于找到正经的答案。正常训练啥事没有,固定batchnorm层准备finetune,迭代几次之后数值就会变得特别大,慢慢就会变成nan,改来改去的也没解决,一开始以为以为没有在卷积层之后接着一个bn层,后来除了最后一层没有加bn层还是会这样 我 我的红呢说道: 2021年3月18日 下午11:28网络结构大概是串联两个编码器解码器,解码器共享参数 O Oldpan说道: 2021年3月28日 下午8:46BN层还是比较重要的,不光是训练,还是推理时候也会避免NAN z zzy说道: 2019年4月22日 上午12:36我最近模型中就出现了nan的情况,但是有意思的是每次都是在固定的训练次数下出现,无论打不打乱顺序都是训练到一个固定批次后,模型中一个liner的参数出现了nan,我检查了输入的数据都是没有问题的,有意思的是,如果我在出现nan的前一步把模型保存下来,然后再加载模型继续训练就不会立即出现nan,训练一段时间后模型参数又会有nan O Oldpan说道: 2019年4月22日 上午9:33你换一下训练批次-batchsize试试,可能与batchsize有关系 略 略略略说道: 2022年3月13日 下午4:22我试了一下确实修改batchsize之后就没问题了,why? Dontation![]() 如果你与我志同道合于此,很愿意与你交流 如果你喜欢我的内容,欢迎关注和支持~ -------这是人工分割线------- 联系我请关注公众号哦关注 oldpan博客 不错过老潘的最新文章。公众号回复"666"获取老潘的宝藏资料(C++、CUDA、Python、深度学习、算法),希望与你交朋友~ 公众号![]() ![]() “逆转裁判”有趣单词 点击进入 最新评论 略 罗密: “老潘,想找你帮做一个ai模型工业部署,有…” 5月 28, 07:05 略 老牛: “我的博客又复活了 已添加友链” 3月 12, 10:48 略 Termi: “来催更了(不是)![]()
友链 资源 RSS 洛奇 Copyright 2024 Oldpan的个人博客. All Rights Reserved. Thanks the theme by Kratos 陕ICP备17018520号-1 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |