49

我想知道如何stop_gradient在 tensorflow 中使用,文档对我来说并不清楚。

我目前正在使用stop_gradientCBOW word2vec 模型中的词嵌入来产生损失函数的梯度。我只想获得价值,而不是进行反向传播(因为我正在生成对抗性示例)。

目前,我正在使用代码:

lossGrad = gradients.gradients(loss, embed)[0]
real_grad = lossGrad.eval(feed_dict)

但是当我运行它时,它无论如何都会进行反向传播!我做错了什么,同样重要的是,我该如何解决这个问题?

澄清:为了澄清“反向传播”,我的意思是“计算值和更新模型参数”。

更新

如果我在第一个训练步骤之后运行上面的两行,那么在 100 个训练步骤后我得到的损失与我不运行这两行时不同。我可能从根本上误解了 Tensorflow。

我尝试set_random_seed在图形声明的开头和每个训练步骤之前都使用设置。多次运行之间的总损失是一致的,但在包括/排除这两条线之间却不一致。因此,如果不是 RNG 导致了差异,也不是训练步骤之间模型参数的意外更新,您知道什么会导致这种行为吗?

解决方案

Welp,这有点晚了,但这是我解决它的方法。我只想优化一些但不是全部变量。我认为防止优化某些变量的方法是使用stop_grad- 但我从来没有找到一种方法来实现这一点。也许有一种方法,但对我有用的是将我的调整optimizer为仅优化变量列表。所以而不是:

opt = tf.train.GradientDescentOptimizer(learning_rate=eta)
train_op = opt.minimize(loss)

我用了:

opt = tf.train.GradientDescentOptimizer(learning_rate=eta)
train_op = opt.minimize(loss, var_list=[variables to optimize over])

这阻止opt了更新不在var_list. 希望它也适合你!

4

2 回答 2

62

tf.stop_gradient提供了一种在反向传播期间不计算某些变量的梯度的方法。

例如,在下面的代码中,我们有三个变量w1w2w3input x。损失是square((x1.dot(w1) - x.dot(w2 * w3)))。我们希望尽量减少这种损失,w1但希望保持w2w3修复。为了实现这一点,我们可以把tf.stop_gradient(tf.matmul(x, w2*w3)).

在下图中,我将 、 和 从它们的初始值绘制w1w2训练w3迭代的函数。可以看出w2w3保持不变,而 w1 变化直到等于w2 * w3

显示 w1 只学习但不学习的图像w2w3

显示 w1 只学习但不学习 w2 和 w3 的图像

import tensorflow as tf
import numpy as np

w1 = tf.get_variable("w1", shape=[5, 1], initializer=tf.truncated_normal_initializer())
w2 = tf.get_variable("w2", shape=[5, 1], initializer=tf.truncated_normal_initializer())
w3 = tf.get_variable("w3", shape=[5, 1], initializer=tf.truncated_normal_initializer())
x = tf.placeholder(tf.float32, shape=[None, 5], name="x")


a1 = tf.matmul(x, w1)
a2 = tf.matmul(x, w2*w3)
a2 = tf.stop_gradient(a2)
loss = tf.reduce_mean(tf.square(a1 - a2))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
gradients = optimizer.compute_gradients(loss)
train_op = optimizer.apply_gradients(gradients)
于 2016-09-06T19:10:39.937 回答
32

tf. gradients(loss, embed)计算张量loss相对于张量的偏导数embed. TensorFlow 通过反向传播计算这个偏导数,因此评估结果tf. gradients(...)执行反向传播是预期的行为。但是,评估该张量不会执行任何变量更新,因为表达式不包含任何赋值操作

tf.stop_gradient()是一种操作,它在前向方向上充当恒等函数,但阻止累积梯度在反向方向上流过该算子。它不会完全阻止反向传播,而是阻止单个张量对为表达式计算的梯度做出贡献。该操作的文档包含有关该操作以及何时使用它的更多详细信息。

于 2015-11-16T05:59:59.310 回答