使用Adam解算器发出NaN

时间:2016-11-07 18:55:30

标签: python tensorflow deep-learning

我与Adam解决方案一起训练网络,并遇到了问题,优化命中了' nan'在某些时候,但到目前为止,损失似乎很好地减少了。它只发生在一些特定的配置上,经过几千次迭代。例如,批量大小为5的网络将出现问题,而批量大小为1的网络则有效。所以我开始调试我的代码:

1)我想到的第一件事就是在网络命中时检查输入,但它们看起来合理(正确标记的基本事实和输入的值范围很好)

2)在搜索时我发现了kernel = tf.verify_tensor_all_finite(kernel, 'kernel') in_tensor = tf.verify_tensor_all_finite(in_tensor, 'in_tensor') tmp_result = tf.nn.conv2d_transpose(value=in_tensor, filter=kernel, output_shape=output_shape, strides=strides, padding='SAME') tmp_result = tf.verify_tensor_all_finite(tmp_result, 'convres') 并且我把这些全部放在我的代码上看,哪个张量首先变成了' nan'。 我可以将问题缩小到以下几行:

InvalidArgumentError (see above for traceback): convres : Tensor had NaN values
     [[Node: upconv_logits5_fs/VerifyFinite_2/CheckNumerics = CheckNumerics[T=DT_FLOAT, _class=["loc:@upconv_logits5_fs/conv2d_transpose"], message="convres", _device="/job:localhost/replica:0/task:0/gpu:0"](upconv_logits5_fs/conv2d_transpose)]]
     [[Node: Adam/update/_2794 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_154_Adam/update", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

抛出错误,其中包含:

upconv_logits5_fs

现在我不确定这里发生了什么。

我想,在前进过程中一切都进展顺利,因为标量损失并没有触发错误,而且内核&输入仍然是有效的数字。似乎某些Adam更新节点将我的tf.nn.softmax_cross_entropy_with_logits()的值修改为nan。这个转置的卷积操作是我网络的最后一个,因此是第一个要更新的网络。

我正在处理tf.verify_tensor_all_finite()损失并将tf.sqrt(0.0 + epsilon)放在其所有内容和输出中,但它们不会触发错误。我能得出的唯一结论是,亚当解算器可能存在数值问题。

  • 您对此结论有何看法?
  • 有人知道如何继续或我可以尝试什么?

非常感谢您的帮助。

修改 我能够通过将求解器 epsilon 参数从1e-8增加到1e-4来解决我的问题。似乎我的一些参数往往具有非常小的零方差,并导致{{1}},这导致了数值问题。

4 个答案:

答案 0 :(得分:16)

我多次遇到同样的问题。这个问题背后的原因是使用softmax和crossentropy。因此,当您计算渐变并以零或inf潜水时,您将获得正在传播的nan,抛出所有参数。

很少有人建议避免这个问题

  • 如果错误开始增加,则之后出现NaN:由于学习率过高而出现分歧
  • 如果NaN突然出现:饱和单元产生不可微分的梯度
  • 由于log(0)
  • 导致的NaN计算
  • NaN由于浮点问题(高权重)或输出激活
  • 0/0,inf / inf,inf * weight ...

解决方案:

  • 降低学习率
  • 更改权重初始化
  • 使用L2规范
  • 安全softmax(小值添加到log(x))
  • 渐变剪辑

在我的情况下,学习率解决了这个问题,但我仍然在努力优化它

答案 1 :(得分:1)

Feras的答案中没有包括的另一步骤,花了我一天的调试时间。

提高变量的精度。我有一个网络,其中许多变量被定义为float16。除了Adam和Adadelt之外,该网络对于所有优化器都运行良好。经过数小时的调试,我切换到ft.float64并成功了。

答案 2 :(得分:0)

这是一个数值稳定性问题。我建议尝试较低的学习率,看看是否可以解决您的问题。

答案 3 :(得分:0)

这可能对我的情况来说很特殊,但可能仍然可以帮助其他人。

我的损失突然变成了nan而事前没有达到特别大的价值。我检查了我的数据是否没有损坏,尝试使用学习速率,添加了clipnorm,批处理规范化层等等,都没有成功。

我实际上是在模型中的分母上添加了一个随机的epsilon(以避免被0除),但是没有注意它的范围。通过将minval从0更改为1e-18可以解决我的问题。

rand_num = Lambda(lambda input: K.random_uniform(tf.shape(input), minval = 1e-18, maxval=1e-17))(s_p)

我猜一些随机选择的值太小而无法满足其目的,无法将潜在的除以零。