tensorflow NAN常见原因和解决方法

最近遇到NAN的问题,花了很久才真正解决。发现网上大部分解决方法都不对或者不彻底,因此单独总结一下。

 

一、NAN原因

所有NAN都是这个原因:正向计算时节点数值越界,或反向传播时gradient数值越界;

无论正反向,数值越界基本只有三种操作会导致:

a) 节点/W/gradient数值逐渐变大直至越界

b) 有除零操作,包括0/0。

c) 输入数据存在异常,过大/过小的输入,导致瞬间NAN

 

二、现象

两者的现象可能一样,绝大多数情况下,NAN都发生在训练一段时间后,报loss NAN,如果你打印了gradient也可能先报gradient NAN。

 

三、危险信号

输入没有归一化、tf.sqrt(), relu()+cosine(), 全relu()激活, 过大的learning rate

如果你的NN网络中包含上述三种情况的任何一个,则极有可能触发NAN

 

四、解决方法

0)首先检查你的输入

如果你的输入feature没有归一化,离线归一化到0~1;如果已经归一化,但是不确定是否有个别异常数据,使用tf.clip_by_value(feature, 0.0, 1.0) 对数据进行异常截断。

1) 不推荐: 前向网络内部使用 tf.clip_by_value

网上常见这种方法。这种方法不太好;前向计算时对节点使用会导致梯度消失。反向传播时对gradient使用过于严苛。可以使用tf.clip_by_globalnorm(gradients, clip_norm=1.0) 让收敛更加稳定。该函数在梯度小时不进行操作,在梯度过大时进行全局归一化而不是直接对个别graident截断。对NAN改善有辅助作用。但如果当前代码存在0/2/3/4问题,则不能寄希望于该方法解决已有的NAN问题。

2)检查正向计算运算边界

现象:loss值或predict score值逐渐变大或有大幅波动,直至NAN

场景:如果你的前向计算都是relu()激活,缺少类似cosine/tanh/sigmoid/layer_norm这种带有归一化能力的激活或norm操作,则很可能随着W方差的增大,出现个别节点数值过大的问题。

解决方法:

a) 减少learning_rate。尝试把lr减少10倍、50倍、100倍。百试不爽,该类问题绝大部分可以得到解决(注意lr也别太小,否则收敛过慢浪费时间,要在速度和稳定性之间平衡)

b) loss增加L2正则,避免随着迭代W越来越大,直至线性运算结果越界;一般L2后不会再NAN,但要注意对效果的影响,如果效果显著变差则不推荐使用。

c) 检查你的variable初始化值域,确保w初始值足够小,常用初始化|w|<<1; 推荐使用 tf.truncated_normal_initializer(stddev=0.02)

d) 若仍然不行,则应考虑在尽量靠前的位置增加tanh/cosine等有收敛边界的激活函数,但这会影响梯度传播,慎用,尽量使用前几种方法。

3)检查正向运算除0操作

现象:loss值或predict score正常且稳定,甚至逐渐收敛,但突然loss NAN

场景:数据中存在某些值,导致除0。常见于除法操作、归一化操作或cosine计算中。正向除零比较好发现,也比较好改,但应注意正向改好后反向是不是还有问题。

解决方法:

a) ctrl+F 检查所有tf.div和/关键字,确保分母不会为0. 对于分母>=0的情景,可以使用+0.001这种方式保证非0

b) 应警惕在上一步修改后,反向梯度是否仍有除0场景。如cosine中,若分母为0,则反向梯度也是NAN,只改正向是不够的

4)检查反向除0操作

现象:与3相同

场景:

a) 所有的开方操作,如开平方 y=tf.sqrt(a) 如果a为0或接近与0,会导致gradient(y,a)=NAN

b) cosine操作,y=cosine(a, b),如果||a||或||b||接近0(由于有6次方操作,a[*]均<0.01就会导致float越界),gradient会NAN;这种情况在a=relu(c), b=relu(d)的时候会非常严重,因为relu()有一定概率输出全零值。

解决方法:

a) 搜索所有tf.sqrt,尽量删除。如loss=均方差(y,y_),千万不要在均方差外面再套一个开方。否则当loss接近与0时会梯度NAN

b) 对于relu()+cosine()。删除relu()操作,cosine前不要加激活函数,cosine本来就是非线性变换,不需要两个紧邻的非线性变换。线性计算得到的a,b, 基本不会有L2接近0的情形。

 

五、参考资料

https://stackoverflow.com/questions/33962226/common-causes-of-nans-during-training

https://stackoverflow.com/questions/44497446/loss-in-tensorflow-suddenly-turn-into-nan

 

版权声明:转载请注明出处:苏冉旭的博客 https://blog.csdn.net/suranxu007/article/details/87266191

你可能感兴趣的:(机器学习)