神经网络出现nan原因?以及解决
之前在TensorFlow中实现不同的神经网络,作为新手,发现经常会出现计算的loss中,出现Nan值的情况,总的来说,TensorFlow中出现Nan值的情况有两种,一种是在loss中计算后得到了Nan值,另一种是在更新网络权重等等数据的时候出现了Nan值,本文接下来,首先解决计算loss中得到Nan值的问题,随后介绍更新网络时,出现Nan值的情况。
Loss计算中出现Nan值
在搜索以后,找到StackOverflow上找到大致的一个解决办法(原文地址:https://stackoverflow.com/questions/33712178/tensorflow-nan-bug),大致的解决办法就是,在出现Nan值的loss中一般是使用的TensorFlow的log函数,然后计算得到的Nan,一般是输入的值中出现了负数值或者0值,在TensorFlow的官网上的教程中,使用其调试器调试Nan值的出现,也是查到了计算log的传参为0;而解决的办法也很简单,假设传参给log的参数为y,那么在调用log前,进行一次数值剪切,修改调用如下:
loss = tf.log(tf.clip_by_value(y,1e-8,1.0))
这样,y的最小值为0的情况就被替换成了一个极小值,1e-8,这样就不会出现Nan值了,StackOverflow上也给出了相同的解决方案。于是,我就采用了上述的解决方案对于log的参数进行数值限制,但是我更加复杂化了这个限制。
tf.clip_by_value这个函数,是将第一个参数,限制在第二、三个参数指定的范围之内,使用这个函数的原意是要避免0值,并没有限制最大值,因而我将限制的调用修改如下:
loss = tf.log(tf.clip_by_value(y,1e-8,tf.reduce_max(y)))
这样就确保了对于y值的剪切,不会影响到其数值的上限。但是在实际的神经网络中使用的时候,我发现这样修改后,虽然loss的数值一直在变化,可是优化后的结果几乎是保持不变的,这就存在问题了。
经过检查,其实并不能这么简单的为了持续训练,而修改计算损失函数时的输入值。这样修改后,loss的数值很可能(存在0的话确定就是)假的数值,会对优化器优化的过程造成一定的影响,导致优化器并不能正常的工作。
要解决这个假的loss的方法很简单,就是人为的改造神经网络,来控制输出的结果,不会存在0。这就需要设计好最后一层输出层的激活函数,每个激活函数都是存在值域的,详情请见博客http://www.jianshu.com/p/ffd3e63f39ef,比如要给一个在(0,1)之间的输出(不包含0),那么显然sigmoid是最好的选择。不过需要注意的是,在TensorFlow中,tf.nn.sigmoid函数,在输出的参数非常大,或者非常小的情况下,会给出边界值1或者0的输出,这就意味着,改造神经网络的过程,并不只是最后一层输出层的激活函数,你必须确保自己大致知道每一层的输出的一个范围,这样才能彻底的解决Nan值的出现。
举例说明就是TensorFlow的官网给的教程,其输出层使用的是softmax激活函数,其数值在[0,1],这在设计的时候,基本就确定了会出现Nan值的情况,只是发生的时间罢了。
更新网络时出现Nan值
更新网络中出现Nan值很难发现,但是一般调试程序的时候,会用summary去观测权重等网络中的值的更新,因而,此时出现Nan值的话,会报错类似如下:
InvalidArgumentError (see above for traceback): Nan in summary histogram for: weight_1
这样的情况,一般是由于优化器的学习率设置不当导致的,而且一般是学习率设置过高导致的,因而此时可以尝试使用更小的学习率进行训练来解决这样的问题。
提供一个小小的debug经验,其实是我之前遇到的很傻的坑,可能不能解决题主的问题。
log(0)
log(0) * 0
当网络训练到达一定程度的时候,模型对分类的判断可能会产生0这样的数值,log(0)本身是没有问题的,-inf可以安全的参与绝大部分运算,除了(-inf * 0),会产生NaN。NaN的话,一旦参与reduce运算会让结果完蛋的… 因此呢,如果有
y_truth * log(y_predict)
# when y_truth[i] is 0, it is likely that y_predict[i] would be 0
这样的表达式,要考虑对log中的变量进行clip. 比如
safe_log = tf.clip_by_value(some_tensor, 1e-10, 1e100)
bin_tensor * tf.log(safe_log)
这种错误实在有点傻,不过坑了我好几个小时。并且呢,这样的错误十分肯定会造成断崖式下跌。 希望对题主有所帮助。(不然就当做我的一次笔记吧~)
当然除了log函数之外,exp也是产生NaN的大户,也要多加防范。
神经网络出现nan原因?以及解决的更多相关文章
- [Python Debug]Kernel Crash While Running Neural Network with Keras|Jupyter Notebook运行Keras服务器宕机原因及解决方法
最近做Machine Learning作业,要在Jupyter Notebook上用Keras搭建Neural Network.结果连最简单的一层神经网络都运行不了,更奇怪的是我先用iris数据集跑了 ...
- SVN 错误 Access to SVN Repository Forbidden的原因及解决方法
原创文章,转载请注明出处:http://www.cnblogs.com/baipengzhan/p/SVN_Access_to_SVN_Repository_Forbidden.html 当我们新 ...
- coreseek常见错误原因及解决方法
coreseek常见错误原因及解决方法 Coreseek 中文全文检索引擎 Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和 ...
- RDS MySQL 空间问题的原因和解决
来源:https://help.aliyun.com/knowledge_detail/41739.html RDS MySQL 空间问题的原因和解决 更新时间:2016-07-22 17:20:14 ...
- .NET 3.5 安装错误的四个原因及解决方法
.net framework 3.5 安装错误的四个常见原因及解决方法,飓风软件站整理,转载请注明. 1.清除所有版本 .NET Framework 安装错误后在系统中遗留的文件: 如果您以往安装过 ...
- jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法
jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法 在调用一个jquery的ajax方法时我们有时会需要该方法返回一个值或者给某个全局变量赋值,可是我们 ...
- Java ConcurrentModificationException异常原因和解决方法
Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.u ...
- 关于Node.js的httpClieint请求报错ECONNRESET的原因和解决措施
背景说明 最近在工作项目中有下面一个场景: 使用Node.js的express框架实现了一个文件系统服务器端,其中有个API用于客户端上传文件.客户端使用Node.js的HttpClient来调用服务 ...
- 各种编码问题产生原因以及解决办法---------响应编码,请求编码,URL编码
响应编码 产生原因以及解决办法: 示例: package cn.yzu; import java.io.IOException; import javax.servlet.ServletExcept ...
随机推荐
- appium 中文API 集
参考:https://testerhome.com/topics/3711 根据appium 1.4.13.1版本整理,1.5弃用了find by name 所以更新了下如有错误请多多指正谢谢@lyl ...
- poj 3255 Roadblocks 次短路(两次dijksta)
Roadblocks Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Total S ...
- ASP.NET Web Pages:帮助器
ylbtech-.Net-ASP.NET Web Pages:帮助器 1.返回顶部 1. ASP.NET Web Pages - 帮助器 Web 帮助器大大简化了 Web 开发和常见的编程任务. AS ...
- Appium+python自动化8-Appium Python API
Appium+python自动化8-AppiumPython API 前言: Appium Python API全集,不知道哪个大神整理的,这里贴出来分享给大家. 1.contexts conte ...
- 模拟估算器:scikit-learn Estimator
转载:https://www.toutiao.com/i6606193174010397187/ 当一个数据科学项目刚刚开始时,关键是要尽可能快地走向一个最小可行的产品(MVP).这个MVP将包含最终 ...
- ORACLE中index的rebuild(转)
Oracle里大量删除记录后,表和索引里占用的数据块空间并没有释放. table move可以释放已删除记录表占用的数据块空间,整理碎片.如果将表格用move方式整理碎片后,索引将失效,这时需要将索引 ...
- uva-10420-排序
根据国家名字统计人数,然后排序 #include<stdio.h> #include<iostream> #include<queue> #include<m ...
- 0_Simple__UnifiedMemoryStreams
使用 OpenMP 和 pthreads 两种环境,利用实现统一内存编址,计算基本的矩阵乘法 result = α * A * x + β * result . ▶ 源代码 #include < ...
- PHP把excel导入mysql数据库最常用的方法
Posted on 2011-03-25 09:16 PHP博客 阅读(1316) 评论(0) 编辑 收藏 引用 网摘 PHP把excel(xls)文件导入mysql数据库最常用的方法就是先把xls ...
- 25. instr用法
很多时候,我们要进行字符串匹配,在SQL语句中,我们通常使用like来达到我们搜索的目标.但经过实际测试发现,like的效率与instr函数差别相当大.下面是一些测试结果: select instr( ...