如何在TensorFlow中应用渐变剪裁?

时间:2016-04-08 11:09:55

标签: python machine-learning tensorflow deep-learning lstm

考虑example code

我想知道如何在可能爆炸梯度的RNN上对此网络应用渐变剪裁。

tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)

这是一个可以使用的例子,但我在哪里介绍呢? 在defN的RNN

    lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)
    # Split data because rnn cell needs a list of inputs for the RNN inner loop
    _X = tf.split(0, n_steps, _X) # n_steps
tf.clip_by_value(_X, -1, 1, name=None)

但这不是有意义的,因为张量_X是输入而不是渐变的被剪裁的东西?

我是否必须为此定义自己的优化器,或者是否有更简单的选项?

7 个答案:

答案 0 :(得分:128)

在计算渐变之后,但在应用它们来更新模型的参数之前,需要进行渐变剪切。在您的示例中,这两件事都由AdamOptimizer.minimize()方法处理。

为了剪辑渐变,您需要按照this section in TensorFlow's API documentation中的描述显式计算,剪辑和应用它们。具体而言,您需要使用以下内容替换minimize()方法的调用:

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
gvs = optimizer.compute_gradients(cost)
capped_gvs = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in gvs]
train_op = optimizer.apply_gradients(capped_gvs)

答案 1 :(得分:100)

尽管看起来很受欢迎,但您可能希望按照其全局规范剪切整个渐变:

optimizer = tf.train.AdamOptimizer(1e-3)
gradients, variables = zip(*optimizer.compute_gradients(loss))
gradients, _ = tf.clip_by_global_norm(gradients, 5.0)
optimize = optimizer.apply_gradients(zip(gradients, variables))

单独剪切每个渐变矩阵会改变它们的相对比例,但也是可能的:

optimizer = tf.train.AdamOptimizer(1e-3)
gradients, variables = zip(*optimizer.compute_gradients(loss))
gradients = [
    None if gradient is None else tf.clip_by_norm(gradient, 5.0)
    for gradient in gradients]
optimize = optimizer.apply_gradients(zip(gradients, variables))

答案 2 :(得分:9)

这实际上是explained in the documentation.

  

调用minimize()会同时计算渐变和   将它们应用于变量。如果要处理渐变   在应用它们之前,您可以分三步使用优化器:

     
      
  • 使用compute_gradients()计算渐变。
  •   
  • 根据需要处理渐变。
  •   
  • 使用apply_gradients()。
  • 应用已处理的渐变   

在他们提供的示例中,他们使用以下3个步骤:

# Create an optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)

# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss, <list of variables>)

# grads_and_vars is a list of tuples (gradient, variable).  Do whatever you
# need to the 'gradient' part, for example cap them, etc.
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]

# Ask the optimizer to apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)

此处MyCapper是限制渐变的任何函数。有用函数列表(tf.clip_by_value()除外)是here

答案 3 :(得分:7)

对于那些想要了解渐变剪辑(通过规范)的人:

每当梯度范数大于特定阈值时,我们剪切渐变范数,使其保持在阈值范围内。此阈值有时设置为5

让渐变为 g ,max_norm_threshold为 j

现在,如果|| g || &GT; j ,我们这样做:

g =( j * g )/ || g ||

这是在tf.clip_by_norm

中完成的实施

答案 4 :(得分:4)

IMO最好的解决方案是用TF的估算器装饰器tf.contrib.estimator.clip_gradients_by_norm包装优化器:

original_optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
optimizer = tf.contrib.estimator.clip_gradients_by_norm(original_optimizer, clip_norm=5.0)
train_op = optimizer.minimize(loss)

这样,您只需要定义一次,而不必在每次梯度计算后运行它。

文档: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm

答案 5 :(得分:2)

渐变剪切基本上有助于爆炸或消失渐变。但是您的损失太高会导致指数梯度流过网络,这可能会导致Nan值。为了克服这个问题,我们在特定范围内剪切渐变(-1到1或根据条件的任何范围)。

clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars

其中grads _and_vars是渐变对(通过tf.compute_gradients计算)及其应用的变量。

剪切后,我们只需使用优化器应用其值。 optimizer.apply_gradients(clipped_value)

答案 6 :(得分:1)

tf.keras很简单!

_z_ValDate  = 
var curDate = vwLossRunData[Policy Effective Date]
return CALCULATE(MAX(vwLossRunData[Valuation date]), FILTER(vwLossRunData, curDate = vwLossRunData[Policy Effective Date]))

此优化器会将所有渐变剪切为optimizer = tf.keras.optimizers.Adam(clipvalue=1.0) 之间的值。

请参见docs