使用Adam解算器发出NaN

zim*_*rmc 12 python deep-learning tensorflow

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

1)我想到的第一件事就是在网络命中'nan'时检查输入,但它们看起来合理(正确标记的地面实况和输入具有可靠的值范围)

2)搜索时我发现了tf.verify_tensor_all_finite(..),我把它全部放在我的代码上看,哪个张量首先成为'nan'.我可以将问题缩小到以下几行:

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')
Run Code Online (Sandbox Code Playgroud)

抛出错误,其中包含:

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"]()]]
Run Code Online (Sandbox Code Playgroud)

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

我想,在前进过程中一切都进展顺利,因为标量丢失没有触发错误,内核和输入仍然是有效数字.似乎有些Adam更新节点修改了我upconv_logits5_fs对nan 的值.这个转置的卷积操作是我网络的最后一个,因此是第一个要更新的网络.

我正在处理tf.nn.softmax_cross_entropy_with_logits()亏损并将tf.verify_tensor_all_finite()其全部输入和输出,但它们不会触发错误.我能得出的唯一结论是,亚当解算器可能存在数值问题.

  • 你怎么看待这个结论?
  • 有没有人知道如何继续或我可以尝试什么?

非常感激您的帮忙.

编辑: 我能够通过将求解器epsilon参数从1e-8增加到1e-4 来解决我的问题.似乎我的一些参数倾向于具有非常小的零方差tf.sqrt(0.0 + epsilon),并且导致数值问题.

小智 19

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

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

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

解决方案:

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

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


Sal*_*ali 6

Feras 的答案中没有包含一个额外的步骤,并且花费了我一天的调试时间。

提高变量的精度。我有一个网络,其中很多变量被定义为 float16。除了 Adam 和 Adadelta 之外,网络对于所有优化器都运行良好。经过几个小时的调试后,我切换到tf.float64并且它工作了。

  • 您能否进一步说明为什么 Adam 需要这种精度? (3认同)

Dav*_*ong 2

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