Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在TensorFlow中应用渐变剪裁?_Python_Tensorflow_Machine Learning_Keras_Deep Learning - Fatal编程技术网

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

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

考虑到这一点

我想知道如何在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 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()应用处理后的渐变
在他们提供的示例中,他们使用以下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)
#创建一个优化器。
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)
只是计算和应用梯度的简写