训练期间nans的常见原因

Aid*_*mez 74 machine-learning neural-network gradient-descent deep-learning caffe

我注意到在培训期间经常出现这种情况NAN.

通常情况下,内部产品/完全连接或卷积层中的重量似乎会被引入.

这是因为梯度计算正在爆发吗?或者是因为重量初始化(如果是这样,为什么重量初始化会产生这种效果)?或者它可能是由输入数据的性质引起的?

这里的首要问题很简单:在培训期间发生NAN的最常见原因是什么?其次,有什么方法可以解决这个问题(为什么它们有效)?

Sha*_*hai 108

好问题.
我多次遇到过这种现象.以下是我的观察:


渐渐爆发

原因:大的渐变会使学习过程偏离轨道.

您应该期望:查看运行时日志,您应该查看每次迭代的损失值.您会注意到从迭代到迭代,损失开始显着增长,最终损失将太大而无法由浮点变量表示,它将变为nan.

你能做什么:减少base_lr(在solver.prototxt中)一个数量级(至少).如果你有几个损层,你应该检查日志,看看渐变炸毁,并降低该层负责loss_weight(在train_val.prototxt)该特定层,而不是一般的base_lr.


不良的学习率政策和准备

原因: caffe无法计算有效的学习率并获得'inf''nan'取而代之的是,此无效率会使所有更新倍增,从而使所有参数无效.

您应该期待什么:查看运行时日志,您应该看到学习率本身变为'nan',例如:

... sgd_solver.cpp:106] Iteration 0, lr = -nan
Run Code Online (Sandbox Code Playgroud)

你能做什么:修复影响你'solver.prototxt'文件中学习率的所有参数.
例如,如果您使用lr_policy: "poly"而忘记定义max_iter参数,则最终会得到 lr = nan...
有关caffe中学习速率的更多信息,请参阅此主题.


故障丢失功能

原因:有时损失层中损失的计算会导致nans出现.例如,InfogainLoss使用具有非标准化值的 Feed ,使用带有错误的自定义丢失层等.

您应该期待什么:查看运行时日志,您可能不会注意到任何异常:丢失逐渐减少,并且突然nan出现.

你能做什么:看看你是否可以重现错误,将打印输出添加到损失层并调试错误.

例如:一旦我使用了一个损失,通过批量中标签出现的频率来标准化惩罚.碰巧的是,如果其中一个训练标签根本没有出现在批次中 - 计算出nan的损失就会产生.在这种情况下,使用足够大的批次(相对于集合中的标签数量)足以避免此错误.


输入错误

原因:你有输入nan!

你应该期待什么:一旦学习过程"击中"这个错误的输入 - 输出就变成了nan.查看运行时日志,您可能不会注意到任何异常:丢失逐渐减少,并且突然nan出现.

你可以做的:重新建立自己的输入数据集(lmdb/leveldn/HDF5 ...),请确保你没有在你的训练/验证集坏图像文件.对于调试,你可以建立一个简单的网,读取输入层,具有在它上面的虚拟损失,并通过全部投入运行:如果其中一个出现故障,该虚拟网也应该产生nan.


"Pooling"层中跨步大于内核大小

出于某种原因,选择stride> kernel_size进行汇总可能会导致nans.例如:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}
Run Code Online (Sandbox Code Playgroud)

nans in的结果y.


不稳定性 "BatchNorm"

据报道,在某些设置下,由于数值不稳定,"BatchNorm"层可能会输出nans.
这个问题在bvlc/caffe中提出,PR#5136试图修复它.


最近,我才知道的debug_info标志:设置debug_info: true'solver.prototxt'将朱古力打印训练过程中记录更多的调试信息(包括梯度大小和激活值):这些信息可以在发现梯度blowups等问题,在训练过程中提供帮助.


小智 5

就我而言,原因是未在卷积/反卷积层中设置偏差。

解决方法:在卷积层参数中加入以下内容。

bias_filler {
      type: "constant"
      value: 0
    }
Run Code Online (Sandbox Code Playgroud)