Python 如何在TensorFlow中应用渐变剪裁?
考虑到这一点 我想知道如何在RNN上的这个网络上应用渐变剪裁,在这个网络上有可能爆发渐变Python 如何在TensorFlow中应用渐变剪裁?,python,tensorflow,machine-learning,keras,deep-learning,Python,Tensorflow,Machine Learning,Keras,Deep Learning,考虑到这一点 我想知道如何在RNN上的这个网络上应用渐变剪裁,在这个网络上有可能爆发渐变 tf.clip_by_value(t, clip_value_min, clip_value_max, name=None) 这是一个可以使用的示例,但是我在哪里介绍这个呢? 在RNN的定义中 lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0) # Split data because rnn cell needs a
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)
这是一个可以使用的示例,但是我在哪里介绍这个呢?
在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是输入,而不是梯度,要裁剪什么
我是否必须为此定义自己的优化器,或者是否有更简单的选项?梯度剪裁需要在计算梯度之后,但在应用它们来更新模型参数之前进行。在您的示例中,这两件事都由
AdamOptimizer.minimize()
方法处理
为了剪裁渐变,需要按照中所述显式计算、剪裁和应用渐变。具体地说,您需要将对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)
尽管看起来很流行,但您可能希望按照全局标准剪裁整个渐变:
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))
在TensorFlow 2中,磁带计算梯度,优化器来自Keras,我们不需要存储更新op,因为它会自动运行,而不会将其传递给会话:
optimizer = tf.keras.optimizers.Adam(1e-3)
# ...
with tf.GradientTape() as tape:
loss = ...
variables = ...
gradients = tape.gradient(loss, variables)
gradients, _ = tf.clip_by_global_norm(gradients, 5.0)
optimizer.apply_gradients(zip(gradients, variables))
这实际上是正确的:
调用minimize()会同时计算梯度和
将它们应用于变量。如果要处理渐变
在应用它们之前,您可以分三步使用优化器:
- 使用Compute_gradients()计算渐变
- 根据需要处理渐变
- 使用Apply_gradients()应用处理后的渐变
# 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)
#创建一个优化器。
opt=梯度下降优化(学习率=0.1)
#计算变量列表的梯度。
梯度和变量=选择计算梯度(损失)
#grads_和_vars是元组列表(梯度、变量)。你做什么就做什么
#需要添加“渐变”部分,例如封盖等。
有上限的年级和变量=[(我的上限(gv[0]),gv[1]),适用于年级和变量中的gv]
#请优化器应用带封顶的渐变。
选择应用梯度(上限梯度和变量)
这里
MyCapper
是限制渐变的任何函数。有用函数的列表(除了tf.clip\u by_value()
)是。对于那些想了解渐变剪裁(按标准)概念的人:
当梯度范数大于某个特定阈值时,我们剪裁梯度范数,使其保持在阈值内。此阈值有时设置为5
设梯度为g,最大范数阈值为j
现在,如果| |g| |>j,我们会:
g=(j*g)/|g||
这是在梯度剪裁中完成的实现,在梯度爆炸或消失的情况下基本上是有帮助的。假设您的损失太高,这将导致指数梯度在网络中流动,从而可能导致Nan值。为了克服这一问题,我们将渐变剪裁在特定范围内(-1到1或根据条件的任何范围)
clipped_value=tf.clip_by_value(grad,-range,+range),var)表示梯度、梯度中的var和变量
其中grads_和_vars是一对渐变(通过tf.compute_gradients计算)及其将应用的变量
剪裁之后,我们只需使用优化器应用它的值。
优化器。应用梯度(剪裁的值)
在我看来,最好的解决方案是用TF的estimator decorator包装优化器TF.contrib.estimator.clip\u gradients\u by\u 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)
这样,您只需定义一次,而不是在每次渐变计算后运行它
文件:
这对tf.keras来说很容易强>
optimizer = tf.keras.optimizers.Adam(clipvalue=1.0)
此优化器将所有渐变剪裁为[-1.0,1.0]
之间的值
请参阅。Styrke,谢谢您的帖子。您知道下一步要实际运行优化器的迭代吗?通常,优化器被实例化为
optimizer=tf.train.AdamOptimizer(learning\u rate=learning\u rate)。最小化(成本)
,然后优化器的迭代作为optimizer.run()
完成,但使用optimizer.run()
在这种情况下似乎不起作用?好了优化器。应用梯度(capped\gvs)
需要分配给某个x=optimizer。应用梯度(上限值)
然后在你的课程中,你可以训练为x.run(…)
向@remi cuingnet大声呼喊。(不幸的是,被草率的评论者拒绝了)这给了我UserWarning:将稀疏索引转换为包含148331760个元素的密集张量。这可能会消耗大量内存。
因此,我的稀疏渐变会以某种方式转换为密集渐变。你知道如何克服这个问题吗?事实上,(根据tensorflow文档、计算机科学家和逻辑学)剪裁渐变的正确方法是使用tf.clip\u by\u global\u norm
,正如@danijar所建议的clip\u by\u global\u norm()
!在tensorflow文档中,这也被描述为执行渐变剪裁的正确方法:@Escachator这是经验的,取决于您的模型和可能的任务。我要做的是可视化渐变范数tf.global_norm(gradients)
以查看其通常的范围,然后再将其略高于该范围以防止异常值扰乱训练。您会在之后调用opt.minimize()
还是调用其他类似opt.run()的东西
正如对其他答案的一些评论所建议的那样?@reese0106 No,optimizer.minimize(loss)
只是计算和应用梯度的简写