训练期间产生NANs的常见原因是什么?
0 745
0

我注意到在训练期间经常发生这种情况。 通常,它似乎是通过权重引入内部或或卷积层中的。 这是因为梯度爆炸吗?还是因为权重初始化?还是可能是由于输入数据的性质引起的? 有什么方法可以解决这个问题?

收藏
2021-02-03 11:23 更新 karry •  4540
共 1 个回答
高赞 时间
0

好问题。 我也经常遇到这种情况。这是我的观察结果:

梯度爆炸 原因:较大的梯度会使学习过程偏离轨道。 查看运行窗口,应查看每次迭代的损失值。你会注意到,损失在每次迭代之间都开始显着增长,最终损失太大而无法用浮点变量表示,它将变为nan。

将base_lr(在resolver.prototxt中)至少减少一个数量级。如果你有多个损失层,则应检查窗口以了解造成梯度爆炸的是哪一层,并减少loss_weight特定层(在train_val.prototxt中),而不是一般层base_lr。

不良的学习率和参数设置 原因: caffe无法计算出有效的学习率,而得到'inf'或'nan',该无效学习率会乘以所有更新数据,从而使所有参数无效。

查看运行时窗口,你可以看到学习率本身变为'nan',例如:

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

修复所有影响'solver.prototxt'文件学习率的参数。例如,如果使用lr_policy: "poly",却忘记定义max_iter参数,最终将得到 lr = nan...

错误的损失函数 原因:有时,损失层中损失的计算会导致nans出现。例如,InfogainLoss使用非标准化的数据,使用带有bug的自定义损失层等。 看运行窗口,你可能不会注意到任何异常情况:损耗在逐渐减少,突然nan就出现了。

查看是否可以重现错误,将打印输出添加到损失层并调试错误。 例如:一旦我使用了损失函数,就可以按批次中标签出现的频率归一化惩罚。碰巧的是,如果其中一个训练标签根本没有出现在批次中,那么所计算的损失将产生nans。在那种情况下,处理足够大的批次(相对于标签中的标签数量)足以避免此错误。

输入错误 原因:输入nan! 一旦学习过程“完成”,该错误的输入输出就会变成nan。 重新构建输入数据集(lmdb / leveldn / hdf5 ...),以确保训练/验证集中没有不良的图像文件。你可以构建一个简单的网络,该网络读取输入层,在其上具有虚拟损耗和所有输入:如果其中一个输入有故障,则该虚拟网也应产生nan。

"Pooling"层步长比内核大 例如:

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

结果是Y中有NANs。

不稳定的 "BatchNorm" 由于数值的不稳定性,在某些设置"BatchNorm"层下可能会输出nan

Via:https://stackoverflow.com/a/33980220/14964791

收藏
2021-02-03 11:50 更新 anna •  5042