RNN 的 tf.clip_by_value 和 tf.clip_by_global_norm 之间的区别以及如何确定要剪辑的最大值?

Posted

技术标签:

【中文标题】RNN 的 tf.clip_by_value 和 tf.clip_by_global_norm 之间的区别以及如何确定要剪辑的最大值?【英文标题】:Difference between tf.clip_by_value and tf.clip_by_global_norm for RNN's and how to decide max value to clip on? 【发布时间】:2017-12-01 11:34:12 【问题描述】:

想了解在TensorFlow中实现梯度裁剪时tf.clip_by_valuetf.clip_by_global_norm的角色区别。首选哪一个以及如何确定要剪辑的最大值?

【问题讨论】:

【参考方案1】:

TL;DR:使用tf.clip_by_global_norm 进行渐变剪裁。

clip_by_value

tf.clip_by_value 将每个值剪辑到一个张量中,而不管张量中的其他值。例如,

tf.clip_by_value([-1, 2, 10], 0, 3)  -> [0, 2, 3]  # Only the values below 0 or above 3 are changed

因此,它可以改变张量的方向,因此如果张量中的值彼此去相关(梯度裁剪不是这种情况),或者避免在一个可能导致其他地方的 Nan / 无限值的张量(例如,通过使用最小值 epsilon=1e-8 和非常大的最大值进行裁剪)。

clip_by_norm

tf.clip_by_norm 在必要时重新调整一个张量,使其 L2 范数不超过某个阈值。避免在一个张量上爆炸梯度通常很有用,因为您保持梯度方向。例如:

tf.clip_by_norm([-2, 3, 6], 5)  -> [-2, 3, 6]*5/7  # The original L2 norm is 7, which is >5, so the final one is 5
tf.clip_by_norm([-2, 3, 6], 9)  -> [-2, 3, 6]  # The original L2 norm is 7, which is <9, so it is left unchanged

但是,clip_by_norm 仅适用于一个渐变,因此如果您在所有渐变张量上使用它,您将失去平衡(有些会被重新调整,有些则不会,而且不是所有的都具有相同的比例)。

请注意,前两个仅适用于一个张量,而最后一个用于张量列表。

clip_by_global_norm

tf.clip_by_global_norm 重新调整张量列表,使其所有范数的向量的总范数不超过阈值。目标与clip_by_norm 相同(避免爆炸梯度,保持梯度方向),但它同时作用于所有梯度,而不是单独作用于每个梯度(也就是说,如果必要,所有梯度都重新缩放相同的因子,或者它们都没有被重新缩放)。这样更好,因为保持了不同梯度之间的平衡。

例如:

tf.clip_by_global_norm([tf.constant([-2, 3, 6]),tf.constant([-4, 6, 12])] , 14.5)

将两个张量重新缩放14.5/sqrt(49 + 196),因为第一个张量的 L2 范数为 7,第二个为 14,sqrt(7^2+ 14^2)&gt;14.5

这个 (tf.clip_by_global_norm) 是您应该用于渐变剪裁的那个。更多信息请参见this。

选择值

选择最大值是最难的部分。您应该使用最大的值,这样您就不会出现梯度爆炸(其影响可以是出现在张量中的 Nans 或 infinite 值,经过几个训练步骤后的恒定损失/准确性)。 tf.clip_by_global_norm 的值应该比其他的更大,因为由于隐含的张量的数量,全局 L2 范数在机械上会比其他的更大。

【讨论】:

张量的方向是什么意思?你是说标志吗? 我的意思是方向与向量的方向相同:如果将张量中的所有值乘以 2 或 0.5,则不会更改其中不同值之间的比率,所以你不会改变它的方向(它仍然代表同一个方向的运动,只是距离更大)。如果您更改的值比其他值多,那么您确实会更改比率,因此您确实会更改方向,这对于应该指向正确方向(大约在最小值方向)的梯度的情况是不好的. @gdelab 当你说“你应该使用最大的值这样你没有爆炸梯度”时,你指的是什么值?

以上是关于RNN 的 tf.clip_by_value 和 tf.clip_by_global_norm 之间的区别以及如何确定要剪辑的最大值?的主要内容,如果未能解决你的问题,请参考以下文章

loss出现Nan的解决办法(梯度爆炸)

函数积累

Tensor flow 实战Google深度学习框架 笔记Code Part

tensorflow-clip_by_value

tensorflow 将数值限制在一定范围内

tensorflow 将数值限制在一定范围内