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_value
和tf.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)>14.5
这个 (tf.clip_by_global_norm
) 是您应该用于渐变剪裁的那个。更多信息请参见this。
选择值
选择最大值是最难的部分。您应该使用最大的值,这样您就不会出现梯度爆炸(其影响可以是出现在张量中的 Nan
s 或 infinite
值,经过几个训练步骤后的恒定损失/准确性)。 tf.clip_by_global_norm
的值应该比其他的更大,因为由于隐含的张量的数量,全局 L2 范数在机械上会比其他的更大。
【讨论】:
张量的方向是什么意思?你是说标志吗? 我的意思是方向与向量的方向相同:如果将张量中的所有值乘以 2 或 0.5,则不会更改其中不同值之间的比率,所以你不会改变它的方向(它仍然代表同一个方向的运动,只是距离更大)。如果您更改的值比其他值多,那么您确实会更改比率,因此您确实会更改方向,这对于应该指向正确方向(大约在最小值方向)的梯度的情况是不好的. @gdelab 当你说“你应该使用最大的值这样你没有爆炸梯度”时,你指的是什么值?以上是关于RNN 的 tf.clip_by_value 和 tf.clip_by_global_norm 之间的区别以及如何确定要剪辑的最大值?的主要内容,如果未能解决你的问题,请参考以下文章