Python 与Adam solver一起解决问题

Python 与Adam solver一起解决问题,python,tensorflow,deep-learning,Python,Tensorflow,Deep Learning,我正在用Adam解算器训练网络,遇到了一个问题,优化在某个点上遇到了“nan”,但损失似乎在这一点上很好地减少了。这种情况只会发生在一些特定的配置中,并且在几千次迭代之后才会发生。例如,批量大小为5的网络将出现问题,而批量大小为1的网络则可以工作。所以我开始调试我的代码: 1) 我想到的第一件事是当网络到达“nan”时检查输入,但它们看起来是合理的(正确地标记了地面真实值,并且输入具有okayish值范围) 2) 在搜索时,我发现了tf。请验证\u tensor\u all\u finite(.

我正在用Adam解算器训练网络,遇到了一个问题,优化在某个点上遇到了“nan”,但损失似乎在这一点上很好地减少了。这种情况只会发生在一些特定的配置中,并且在几千次迭代之后才会发生。例如,批量大小为5的网络将出现问题,而批量大小为1的网络则可以工作。所以我开始调试我的代码:

1) 我想到的第一件事是当网络到达“nan”时检查输入,但它们看起来是合理的(正确地标记了地面真实值,并且输入具有okayish值范围)

2) 在搜索时,我发现了
tf。请验证\u tensor\u all\u 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')
这会引发一个错误,其内容如下:

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"]()]]
现在我不确定这里发生了什么

我想,在向前传递过程中,一切都进行得很顺利,因为标量丢失不会触发错误,而且内核和输入仍然是有效的数字。似乎有些Adam更新节点修改了my
upconv\u logits5\u fs
的值。这个转置卷积运算是我的网络的最后一个,因此是第一个被更新的

我正在使用一个
tf.nn.softmax\u cross\u entropy\u with\u logits()
loss并将
tf放入。验证它的所有输入和输出上的张量\u all\u finite()
,但它们不会触发错误。我能得出的唯一结论是,Adam解算器可能存在数值问题

  • 你对这个结论怎么看
  • 有人知道如何进行或我可以尝试什么吗
非常感谢你的帮助

编辑:
通过将Solver epsilon参数从1e-8增加到1e-4,我能够解决我的问题。似乎我的一些参数的方差很小甚至为零,这导致了
tf.sqrt(0.0+epsilon)
,这导致了数值问题。

这是一个数值稳定性问题。我建议试着降低学习率,看看这是否能解决你的问题

我曾多次奔向同一个问题。这个问题背后的原因是使用了softmax和交叉熵。所以,当你计算梯度,然后按0或inf下潜时,你得到的是nan,它传播了你所有的参数

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

  • 如果错误开始增加,则随后出现NaN:由于学习率过高而发散
  • 如果NaN突然出现:产生不可微梯度的饱和单元
  • 由于日志(0)导致的NaN计算
  • 由于浮点问题(高权重)或输出激活而导致的NaN
  • 0/0,inf/inf,inf*权重
解决方案:

  • 降低学习率
  • 更改权重初始化
  • 使用L2范数
  • 安全softmax(小值添加到日志(x))
  • 梯度削波

在我的案例中,learning rate解决了这个问题,但我仍在进一步优化它

这是Feras的答案中没有包括的额外步骤,花费了我一天的调试时间


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

这可能是我的情况所特有的,但可能仍然会帮助其他人

我的损失突然转为nan,之前没有达到特别大的价值。我检查了我的数据是否被破坏,尝试使用学习率,添加ClipForm,批量规范化层等等,但没有成功

实际上,我在模型的某个地方给分母加了一个随机ε(以避免被0除),但没有注意它的范围。通过将最小值从0更改为1e-18,我解决了这个问题

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

我猜随机选取的一些值太小,无法达到其目的,并将电位除以零。

如我的问题中所述,我正在使用TF softmax xentropy函数。您知道这是否已经包括“保存”-softmax?我知道,他们的
tf.nn.weighted\u cross\u entropy\u with\u logits()
使用了一个数字保存实现,所以我猜他们对纯交叉熵使用了类似的方法。我也不明白饱和单元是如何导致不扩散梯度的。对于一个乙状结肠激活的饱和神经元来说,梯度接近于0,而对于relu来说,它的常数是恒定的,对吗?你能再解释一下为什么Adam需要这个精度吗?