最近在手撸Tensorflow2版本的Faster RCNN模型,稍后会进行整理。但在准备好了模型和训练数据之后的训练环节中出现了大岔子,即训练过程中loss变为nan。nan表示not a number类型,任意有关nan的运算结果都将得到nan。这可真是一颗老鼠屎坏了一锅粥,一但一个step中出现loss为nan,所有神经元的参数都将被更新为nan,之后的epochs和step中所有预测结果和模型参数都将为nan。

为了弄清楚nan的原因,我检查了每个组件函数以及所用的训练数据是否有误,结果显示都是没问题的。怀疑参数设置,怀疑模型流程写错了.....在大量debug之后,终于找到了症结所在。

1、为什么会出现nan?

nan在数学表示上表示一个无法表示的数,一般表示一个非浮点数(比如无理数)。inf不同于nan,inf是一个超过浮点表示范围的浮点数,其本质仍然是一个数,只是他为无穷大。

在numpy数组中,这些计算会产生nan的结果:

仔细debug整个训练过程, 用如下代码段捕获nan的出现(因为在python中nan不会报错)

import numpy as npif np.any(np.isnan(contents)):print('contents contain nan')

如上一步所见,如果某个数做除0运算,python中将会报出除零错误,但在tensorflow中,除0是不会报错的,只会以结果nan继续运算,nan是一个不可表示的浮点数。这就是为什么会出现nan。

import tensorflow as tfif __name__ == '__main__':# main()tensor = tf.constant([0.])res = tensor/0.result = tf.reduce_mean(res)print(result)

2、Faster RCNN为啥会出现nan loss?

经过捕获,在某张目标物体位于边缘的输入图像step中出现loss为nan的情况。而且这张图像在输入经过anchor encode处理后,所得到的target_boxes, target_scores元素全为0,target_masks中元素全部为-1和0。这意味着模型在encode这张图像时,因为目标物体处于边缘,且尺寸很小,与先验框的尺寸相差较大,导致与之交并比大于positive_threshold的先验框容易超出图像边缘而被滤除,与之交并比小于negetive_threshold的先验框被记为负,未检测到物体。因此target_boxes, target_scores也就全部为0了。

举个例子来说,我们想要检测图片中的主子的头,而样本中存在主子耳朵位于边缘的样本,相比于猫头,猫耳朵的尺寸较小。并且样本中更多的猫头,所以在聚类生成先验anchor时,anchor的尺寸会更接近猫头的尺寸,也就是anchor尺寸较大。在encode输入图像时,就会出现上面的标记检测不到物体的情况。

在计算loss时,分为两部分,预测框得分损失以及预测框坐标损失。score_loss计算过程中并不会出现nan,因为foreground_background_mask不可能全为0。而boxes_loss计算过程中,只考虑那些标记为正样本的anchor框的损失,因此foreground_mask就可能出现全为0的情况,在经过求平均过程的除操作就会产生nan,从而造成整个网络坏死。

import tensorflow as tfscore_loss = tf.nn.softmax_cross_entropy_with_logits(labels=target_scores, logits=pred_scores)
foreground_background_mask = (np.abs(target_masks) == 1).astype(np.int32)
score_loss = tf.reduce_sum(score_loss * foreground_background_mask, axis=[1,2,3]) / np.sum(foreground_background_mask)
score_loss = tf.reduce_mean(score_loss)boxes_loss = tf.abs(target_bboxes - pred_bboxes)
boxes_loss = 0.5 * tf.pow(boxes_loss, 2) * tf.cast(boxes_loss<1, tf.float32) + (boxes_loss - 0.5) * tf.cast(boxes_loss >=1, tf.float32)
boxes_loss = tf.reduce_sum(boxes_loss, axis=-1)
foreground_mask = (target_masks > 0).astype(np.float32)
boxes_loss = tf.reduce_sum(boxes_loss * foreground_mask, axis=[1,2,3]) / np.sum(foreground_mask)
boxes_loss = tf.reduce_mean(boxes_loss)

3、解决方法

思路:

(1)损失截断

捕获nan出现的loss,用0或者一个极小值去替换nan,进行后续的反向传播。相当于此张图像贡献的损失极小接近0,而对模型的参数的调整贡献也极小,并且不会造成网络的坏死。

(2)数据替换

将原训练数据集中的目标处于边缘的图像和空图像进行滤除

(3)聚类生成更接近标注框尺寸的先验框,并将encode输入图像过程中的判断anchor位于图像内的范围扩大。

(4)损失函数改造

总结:被这个bug折磨了好久,也拜它所赐,debug过程中更深入学习Faster RCNN的细节。解决方法只是发现bug后想到的,具体效果等后续训练测试啦。

学疏才浅,欢迎指正。

神经网络训练过程中出现loss为nan,神经元坏死相关推荐

  1. 神经网络测试集loss不变_神经网络训练过程中不收敛或者训练失败的原因

    在面对模型不收敛的时候,首先要保证训练的次数够多.在训练过程中,loss并不是一直在下降,准确率一直在提升的,会有一些震荡存在.只要总体趋势是在收敛就行.若训练次数够多(一般上千次,上万次,或者几十个 ...

  2. 深度神经网络训练过程中为什么验证集上波动很大_图神经网络的新基准

    作者 | 李光明 编辑 | 贾 伟 编者注:本文解读论文与我们曾发文章<Bengio 团队力作:GNN 对比基准横空出世,图神经网络的「ImageNet」来了>所解读论文,为同一篇,不同作 ...

  3. 深度学习网络模型训练过程中的Loss问题合集

    把数据集随机分为训练集,验证集和测试集,然后用训练集训练模型,用验证集验证模型,根据情况不断调整模型,选择出其中最好的模型,再用训练集和验证集数据训练出一个最终的模型,最后用测试集评估最终的模型 训练 ...

  4. pytorch训练过程中loss出现NaN的原因及可采取的方法

    在pytorch训练过程中出现loss=nan的情况 1.学习率太高. 2.loss函数 3.对于回归问题,可能出现了除0 的计算,加一个很小的余项可能可以解决 4.数据本身,是否存在Nan,可以用n ...

  5. pytorch训练 loss=inf或者训练过程中loss=Nan

    造成 loss=inf的原因之一:data underflow 最近在测试Giou的测试效果,在mobilenetssd上面测试Giou loss相对smoothl1的效果: 改完后训练出现loss= ...

  6. dqn在训练过程中loss越来越大_用DQN算法玩FlappyBird

    DQN算法可以用于解决离散的动作问题,而FlappyBird的操作正好是离散的. FlappyBird的游戏状态一般可以通过图像加卷积神经网络(CNN)来进行强化学习.但是通过图像分析会比较麻烦,因为 ...

  7. dqn在训练过程中loss越来越大_强化学习笔记:OpenAI Gym+DQN+Tensorflow2实现

    参考了一些文章,针对OpenAI gym环境,使用tf2.x实现了DQN算法:加上了一些没有太大必要(?)的小功能,比如:自动保存视频,保存训练日志从而利用TensorBoard实现数据可视化,保存和 ...

  8. 模型训练过程中产生NAN的原因分析

    模型训练过程中产生NAN的原因分析 在模型的训练过程中发现,有时在经过多轮训练后loss会突然变为nan.loss变为nan也就使权重更新后的网络里的参数变为了nan,这样就使整个训练无法再进行下去了 ...

  9. dqn在训练过程中loss越来越大_DQN算法实现注意事项及排错方法

    在学习强化学习过程中,自己实现DQN算法时,遇到了比较多的问题,花了好几天的时间才得以解决.最后分析总结一下,避免再走弯路. 有可能开始实现出来的DQN算法,无论怎么训练总是看不错成果.需要注意的地方 ...

最新文章

  1. R语言names函数获取或者设置数据对象名称实战
  2. SQL语句中 LIMIT与OFFSET
  3. Kafka系列2-producer和consumer报错
  4. nfs服务器_Kubernetes集群下部署NFS持久存储
  5. Python_sklearn_回归
  6. (74)Verilog HDL系统函数和任务:$readmemb
  7. There is no Action mapped for namespace / and action name .
  8. ERP人力资源管理系统
  9. SVNServer中的权限问题
  10. 华为 eNSP模拟器安装教程
  11. h5可以获取本机手机号码么_h5页面模板免费制作丨动态h5页面模板挑选
  12. Photoshop CC 2020软件安装教程
  13. 怎么解苹果7手机ID锁
  14. 计算机编程课程顺序_您可以在2月开始免费在线编程和计算机科学课程
  15. 面向对象的五大原则是什么
  16. Android沙箱自动化安全产品
  17. 如何查看Eclipse是32位还是64位?
  18. Cisco Visio Stencil 实体图标下载
  19. windows环境下用python PyFtdi控制ftdi芯片生成方波信号
  20. android控件——继承AdapterView的控件无法使用addView方法

热门文章

  1. GPS差分——差分定位
  2. 【Proteus仿真】8×8LED点阵屏仿电梯数字滚动显示
  3. 涨知识!阿里P7级别面试经验总结,附超全教程文档
  4. 小程序开发经验分享(9)小程序快速上线汇总
  5. 小学生用计算机的方法,多种教学方法在小学信息技术教学中的使用
  6. DNSPod十问魏雪:云游戏的野心有多大?
  7. AE安装包+安装教程
  8. JavaScript API方法
  9. oracle12c 1,oracle12c,各种问题解决方案 1
  10. vue 日期时间选择器_Vue日期时间选择器