经过一定次数的迭代后,成本函数变成了 nan

机器算法验证 机器学习 神经网络 深度学习 梯度下降
2022-02-13 01:03:43

我有一个问题,想听听社区怎么说。假设您正在训练一个深度学习神经网络。实施细节与我的问题无关。我很清楚,如果你选择的学习率太大,你最终会得到一个可能变成 nan 的成本函数(例如,如果你使用 sigmoid 激活函数)。假设我使用交叉熵作为成本函数。典型的二元分类(甚至是使用 softmax 的多类)问题。我也知道为什么会这样。我经常观察到以下行为:我的成本函数很好地降低了,但经过一定数量的 epoch 后,它变成了 nan。降低学习率会使这种情况在以后发生(所以在更多的时期之后)。这真的是因为(例如)梯度下降在非常接近最小值后无法稳定自身并开始疯狂反弹吗?我认为该算法不会完全收敛到最小值,但应该围绕它振荡,在那里或多或少保持稳定......想法?

3个回答

好吧,如果您在成本函数中获得 NaN 值,则意味着输入在函数域之外。例如 0 的对数。或者它可能在解析域中,但由于数值错误,我们会遇到同样的问题(例如,一个小值被四舍五入为 0)。这与无法“安定”无关。

因此,您必须确定给定成本函数的不允许的函数输入值是什么。然后,您必须确定为什么要将该输入输入到成本函数中。您可能必须更改输入数据的缩放比例和权重初始化。或者你只需​​要像 Avis 建议的那样具有自适应学习率,因为成本函数环境可能非常混乱。或者可能是因为其他原因,例如架构中某些层的数值问题。

使用深度网络很难说,但我建议您开始查看输入值到您的成本函数(激活层的输出)的进展,并尝试确定原因。

以下是您可以做的一些事情:

  • 使用 SoftMax 交叉熵函数时:

    由于指数,SoftMax 分子不应该有零值。但是,由于浮点精度,分子可能是一个非常小的值,例如 exp(-50000),它的计算结果基本上为零。(参考

    • 快速修复可能是提高模型的精度(使用 64 位浮点数而不是大概 32 位浮点数),或者只是引入一个限制值的函数,因此任何低于零或正好为零的值都被设为足够接近于零,计算机不会崩溃。例如,在进入 softmax 之前使用 X = np.log(np.max(x, 1e-9))。(参考
  • 您可以使用“FastNorm”之类的方法,它可以提高数值稳定性并减少准确度方差,从而实现更高的学习率并提供更好的收敛性。(参考

  • 检查权重初始化:如果不确定,请使用 Xavier 或 He 初始化。此外,您的初始化可能会导致局部最小值不佳,因此请尝试不同的初始化,看看是否有帮助。

  • 降低学习率,尤其是在前 100 次迭代中获得 NaN 时。

  • NaN 可以由除以零或零或负数的自然对数产生。

  • 尝试逐层评估您的网络并查看 NaN 出现的位置。

一些建议取自StackOverflowKDnuggests上的两篇精彩文章的参考资料

可能的原因:

  1. 梯度爆炸
  2. 您的输入包含 nan (或意外值)
  3. 损失函数没有正确实现
  4. 深度学习框架中的数值不稳定性

您可以检查在输入特定输入时它是否总是变为 nan 或者它是完全随机的。

通常的做法是在每几次迭代后逐步降低学习率。