问题:在深度学习训练中,之前的cost是正常的,突然在某一个batch训练中出现Nan
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问题了。
---------------------
NaNs问题(Dealing with NaNs)
相信很多自己实现过深度学习模型或者训练过深度学习模型的人都会知道,产生NaNs或者Infs是一件特别常见的事情。但是NaNs的问题又往往很棘手,因为出现NaN的原因可能有很多,诊断起来并不容易。
这可能是因为模型中某个地方设置的不是特别合理,或者代码中出现了Bug。也有可能是出现了数值不稳定,数值不稳定问题会进行单独说明。甚至也可能是你的算法出了问题,下面将介绍几种出现NaNs的场景以及如何进行诊断并处理模型训练过程中出现的NaNs。
超参数的设置以及权重初始化(Check Superparameters and Weight Initialization)
通常情况下,尤其是你使用深度学习库训练时,原因大多是超参数设置问题。
最可能是就你的学习率设置过大。一个过大的学习率可能在一个epoch里就让你整个模型产生NaN的输出,所以首先检查学习率,最简单的办法就是设置一个小的学习率。
其次,你的模型里有正则化项吗?看正则项是否设置合理,选择一个大的正则项系数来训练几个epoch看下NaNs有没有消失。
还有一些模型可能对权重的初始化十分敏感,如果权重没有采用合理的初始化方法,或者合适的初始化范围,模型可能会产生NaNs。
关于数值稳定(Numerical Stability)
如果你最终诊断发现是在某个公式计算时产生的NaNs,可能的原因就是这个公式存在数值稳定问题,通常发生在你自己实现的某个公式,例如Softmax,因为深度学习库通常会帮助解决公式中的数值稳定问题。
举个列子:一些nodes在某些输入下产生一个很小的p(x)。
在反向传播时,正确的类别所得到的概率非常小(接近零)的话,这里会有 overflow 的危险。
更加详细的数值稳定讲解参照这篇Blog: Softmax vs. Softmax-Loss: Numerical Stability
算法相关(Algorithm Related)
如果上述方法都不适用,那可能是你的算法出了问题,回头去检查数学公式的实现来确保所有的计算和推导是正确的。
---------------------
在训练神经网络的过程中,经常会遇到当训练进行到一定次数后,cost会变成NaN的问题。在网上搜索相关问题时,发现大多人的观点是认为learn