我有一个问题,想听听社区怎么说。假设您正在训练一个深度学习神经网络。实施细节与我的问题无关。我很清楚,如果你选择的学习率太大,你最终会得到一个可能变成 nan 的成本函数(例如,如果你使用 sigmoid 激活函数)。假设我使用交叉熵作为成本函数。典型的二元分类(甚至是使用 softmax 的多类)问题。我也知道为什么会这样。我经常观察到以下行为:我的成本函数很好地降低了,但经过一定数量的 epoch 后,它变成了 nan。降低学习率会使这种情况在以后发生(所以在更多的时期之后)。这真的是因为(例如)梯度下降在非常接近最小值后无法稳定自身并开始疯狂反弹吗?我认为该算法不会完全收敛到最小值,但应该围绕它振荡,在那里或多或少保持稳定......想法?
经过一定次数的迭代后,成本函数变成了 nan
机器算法验证
机器学习
神经网络
深度学习
梯度下降
2022-02-13 01:03:43
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 出现的位置。
可能的原因:
- 梯度爆炸
- 您的输入包含 nan (或意外值)
- 损失函数没有正确实现
- 深度学习框架中的数值不稳定性
您可以检查在输入特定输入时它是否总是变为 nan 或者它是完全随机的。
通常的做法是在每几次迭代后逐步降低学习率。