有没有一种方法可以在tensorflow中剪切中间的爆炸梯度?

8
问题:一个非常长的RNN网络。
N1 -- N2 -- ... --- N100

对于像 AdamOptimizer 这样的优化器,compute_gradient() 会给出所有训练变量的梯度。然而,在某些步骤中可能会爆炸。
how-to-effectively-apply-gradient-clipping-in-tensor-flow 中提到一种方法可以剪裁大的最终梯度。
但是如何剪裁那些中间的梯度呢?
一种方法可能是手动从 "N100 -> N99" 进行反向传播,剪裁梯度,然后从 "N99 -> N98" 等等进行,但这太复杂了。
因此,我的问题是:有没有更容易剪裁中间梯度的方法?(当然,严格来说,它们在数学意义上不再是梯度)

2
粗略的想法是,将每个层包装成一个 py_func,使用自定义梯度,就像这里所做的一样(https://gist.github.com/harpone/3453185b41d8d985356cbe5e57d67342)。自定义梯度函数将获取反向值的向量并返回剪裁版本。 - Yaroslav Bulatov
剪裁权重和/或激活函数也有助于防止大梯度的出现。 - gizzmole
2个回答

2
@tf.custom_gradient
def gradient_clipping(x):
  return x, lambda dy: tf.clip_by_norm(dy, 10.0)

0

您可以使用custom_gradient装饰器创建一个版本的tf.identity,以剪裁中间的梯度爆炸。

``` from tensorflow.contrib.eager.python import tfe

@tfe.custom_gradient def gradient_clipping_identity(tensor, max_norm): result = tf.identity(tensor)

def grad(dresult): return tf.clip_by_norm(dresult, max_norm), None

return result, grad ```

然后像平常使用identity一样使用gradient_clipping_identity,在反向传播时会剪裁您的梯度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接