考虑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是输入而不是渐变的被剪裁的东西?
我是否必须为此定义自己的优化器,或者是否有更简单的选项?
答案 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 ||
中完成的实施答案 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。