深度学习网络模型训练中loss为nans的总结

在网络训练中经常出现lossnans的情况。

主要原因有如下:


梯度爆炸

原因:巨大的梯度值使model的学习过程off-track。

检测方法:查看运行时日志,您应该查看每个迭代的损失值。您会注意到,损失开始从迭代到迭代显著地增长,最终损失将太大,无法用浮点变量表示,它将成为nan

措施:减少base_lr (在solver.prototxt中) 至少一个数量级。如果model有多个loss_layer,你应该检查日志,查看哪个层导致了梯度爆炸,并减少该层的loss_weight 值  (在train. prototxt中),而不是简单的减少base_lr


不当的学习率策略和参数

原因:caffe无法计算一个合理的学习速率并得到'inf''nan',相反的,这个不合理的学习速率会进一步更新参数,从而使model中所有参数变得没有价值。

检测方法:查看运行时日志,您应该看到学习速率本身变成了'nan',例如:

... sgd_solver.cpp:106] Iteration 0, lr = -nan

措施:修改影响学习速率的所有参数。在solver.prototxt文件中。例如,如果使用的是lr_policy: "poly",而忘记定义max_iter参数,则最终将会出现lr = nan


有关在caffe学习速率的更多信息:https://stackoverflow.com/questions/30033096/what-is-lr-policy-in-caffe。


不当的损失函数

原因:有时损失的计算会导致nans出现。例如,给InfogainLoss 层提供没有进行归一化的输出值,使用带有bug的自定义损失层等。

检测方法:查看运行时日志,可能不会出现任何异常情况:损失值正在逐渐减少,突然就出现了一个nan

措施:看看是否能重现这个错误,在loss_layer加一些输出并调试错误。

例如:有一次使用了一个带有归一化了batch中错误的label次数的loss。如果其中一个label从没有在batch中出现过,那么就会发生这样的情况——loss计算就会产生nans。在这种情况下,处理足够大的batches(相对于数据集中标签的数量)就足以避免这个错误。


错误的输入

理由:model的输入中就有nan

检测方法:一旦训练时“点击”这个错误的输入,输出就会变成nan。查看运行时日志,您可能不会注意到任何异常:丢失正在逐渐减少,突然出现了一个nan。

措施:重建你的输入数据集(lmdb/ leveldn / hdf5…),确保你没有坏图像文件在训练/验证集中。你可以构建一个简单的网络来读取输入层,有一个虚拟的损失值,并且可以遍历所有的输入:如果其中一个输入是错误的,这个虚拟的网络也会产生nan。


池化层中步长比核的尺寸大

当池化层中stride> kernel的时候也会产生nans

如下例所示:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

在y中会产生nans。


归一层(batch_norm_layer)不稳定

据一些反映,在某些归一层的设置中,由于数字的不稳定,“batch_norm”层可能输出nans

这个issue 是在bvlc / caffe提出的, PR #5136是试图修复的方法。


最近,通过对debug_infoflag 'solver.prototxt'中设置debug_info: true可以帮助在caffe训练中输出到log更多的调试信息。(包括梯度大小和激活值):这些信息可以帮助在训练过程中发现梯度爆炸和其他问题。

感谢:

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

你可能感兴趣的:(深度学习,深度学习)