以下这些函数可以用于解决梯度消失或梯度爆炸问题上。
tensorflow 中的clip_by_norm
optimizer = tf.train.AdamOptimizer(learning_rate, beta1=0.5) grads = optimizer.compute_gradients(cost) for i, (g, v) in enumerate(grads): if g is not None: grads[i] = (tf.clip_by_norm(g, 5), v) # clip gradients train_op = optimizer.apply_gradients(grads)
1. tf.clip_by_value
tf.clip_by_value( t, clip_value_min, clip_value_max, name=None )
Returns:A clipped Tensor.
输入一个张量t,把t中的每一个元素的值都压缩在clip_value_min和clip_value_max之间。小于min的让它等于min,大于max的元素的值等于max。
例子:
import tensorflow as tf; import numpy as np; A = np.array([[1,1,2,4], [3,4,8,5]]) with tf.Session() as sess: print sess.run(tf.clip_by_value(A, 2, 5)) >>> [[2 2 2 4] [3 4 5 5]]
2. tf.clip_by_norm
tf.clip_by_norm( t, clip_norm, axes=None, name=None ) Returns:A clipped Tensor.
指对梯度进行裁剪,通过控制梯度的最大范式,防止梯度爆炸的问题,是一种比较常用的梯度规约的方式。
- t: 输入tensor,也可以是list
- t_list[i] * clip_norm / max(L2_norm, clip_norm)
注意上面的t可以是list,所以最后做比较的时候是将t的二范式和clip_norm作比较。看下面的例子:
a = np.array([2.,5.]) b = tf.clip_by_norm(a, 5) with tf.Session() as sess: print(sess.run(tf.norm(a))) print(sess.run(b)) >>> 5.3851647 [1.8569534 4.6423836]
3. tf.clip_by_average_norm
tf.clip_by_average_norm(
t,
clip_norm,
name=None
)
Returns:A clipped Tensor.
其实和tf.clip_by_norm类似,只不过把
例子
a = np.array([3, 4]).astype('float32') e = tf.clip_by_average_norm(a, 1) with tf.Session() as sess: print(sess.run(e)) >>> [1.2 1.6]
4. tf.clip_by_global_norm
tf.clip_by_global_norm(
t_list,
clip_norm,
use_norm=None,
name=None
)
Returns:
list_clipped
: A list of Tensors of the same type as list_t.global_norm
: A 0-D (scalar) Tensor representing the global norm.
注意这里的t_list
是a tuple or list of tensors。
通过权重梯度的总和的比率来截取多个张量的值。t_list
是梯度张量, clip_norm
是截取的比率, 这个函数返回截取过的梯度张量和一个所有张量的全局范数。
t_list[i]
的更新公式如下:
t_list[i] * clip_norm / max(global_norm, clip_norm)
其中global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))
global_norm
是所有梯度的平方和,如果 clip_norm > global_norm
,就不进行截取。
但是这个函数的速度比clip_by_norm()
要慢,因为在截取之前所有的参数都要准备好
该文章转载自:https://cloud.tencent.com/developer/article/1375862