深度学习训练中cost突然出现NaN

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hellonlp/article/details/77503354

问题:在深度学习训练中,之前的cost是正常的,突然在某一个batch训练中出现Nan。

网络搜索的资料:

1. How to avoid that Theano computing gradient going toward NaN https://stackoverflow.com/questions/40405334/how-to-avoid-that-theano-computing-gradient-going-toward-nan

2. 训练深度学习网络时候,出现Nan是什么原因,怎么才能避免? https://www.zhihu.com/question/49346370

3. Theano调试技巧 https://zhuanlan.zhihu.com/p/24857032


其实1中的说法挺好的:

few advises to avoid this problem

  • if error starts increasing then NaN appears afterwards: diverging due to too high learning rate
  • if NaNs appear suddenly: saturating units yielding non-differentiable gradient NaN computation due to log(0)
  • NaN due to floating point issues (to high weights) or activations on the output 0/0, inf/inf, inf*weight...
还可以在加一条:数据检查,送入模型的数据是否有问题。


回归到我自己的问题上,首先把数据检查了下,数据没有问题,但是NaN仍忍出现。

然后把learning rate开小了(各种变小),NaN问题依然存在。沿着learning rate这条路,把gradient都check一遍,把Clip Gradient弄的很厉害,但是NaN问题依然存在。

接着把所有可能出问题的变量依次output出来,追溯到某一个变量在cost出现的NaN那一轮产生了NaN。现在问题就来了,为什么上一轮的gradient没有问题,该变量突然变为NaN呢?

再后来,使用NanGuardMode模式,报错出现big values,更加坚信是gradient过大出现的问题,然后就是各种瞎改gradient。


后来的后来,才蓦然回首发现code中有一个逻辑上的bug,会导致NaN的出现。

简单讲就是使用到某个变量 A = [a_1, a_2, ... a_n ] 及其 Mask MA = [ma_1, ma_2,..., ma_n],需要结合其Mask对其进行softmax操作。 在直接对A进行softmax发现,A中某个值得energy太大(对于某个元素 exp^(a_j)数值非常大),会出问题。为了避免问题,找出A中最大数值max(A),对每个值进行“缩放”,A - max(A)后再计算其每个元素的energy,在结合Mask MA进行softmax计算。

step1. 元素“缩放”:  A' = A - A(max)

step2. 计算energy: exp(A') 

step3. Mask(Mask为0的地方概率要为0): exp(A') * MA

step4. 计算概率: exp(A')  / sum( exp(A') * MA)


潜在除0问题:在step1. “缩放”步骤中,Mask为0的某元素比其他元素大的多,导致在step2.计算energy步骤中Mask为1的元素energy几乎为0。接着step3.Mask步骤中使用MA把energy不为0的地方给掩盖掉,这时候留下的全都是0.....

然后step4.计算概率中sum( exp(A') * MA) 的结果为0,最后就出现除0-->NaN问题了。










猜你喜欢

转载自blog.csdn.net/hellonlp/article/details/77503354