我正在尝试实施Adversarial NN,这需要在交替培训小批量时“冻结”图表的一个或另一个部分。即有两个子网:G和D.
G( Z ) -> Xz
D( X ) -> Y
G
的损失函数取决于D[G(Z)], D[X]
。
首先,我需要在D中训练所有G参数固定的参数,然后在G中参数D中的参数固定。第一种情况下的损失函数在第二种情况下将是负损失函数,并且更新将必须应用于第一或第二子网的参数。
我看到tensorflow有tf.stop_gradient
功能。为了训练D(下游)子网,我可以使用此功能来阻止梯度流到
Z -> [ G ] -> tf.stop_gradient(Xz) -> [ D ] -> Y
tf.stop_gradient
非常简洁地注释,没有内联示例(示例seq2seq.py
太长而且不容易阅读),但看起来它必须在图创建期间调用。 是否意味着如果我想在交替批次中阻止/取消阻止渐变流,我需要重新创建并重新初始化图模型吗?
似乎无法通过tf.stop_gradient
阻止流经G(上游)网络的渐变,对吗?
作为替代方案,我看到可以将变量列表作为opt_op = opt.minimize(cost, <list of variables>)
传递给优化器调用,如果可以获得每个子网范围内的所有变量,这将是一个简单的解决方案。 可以为tf.scope获得<list of variables>
吗?
答案 0 :(得分:63)
正如您在问题中提到的,实现此目的的最简单方法是使用对opt.minimize(cost, ...)
的单独调用创建两个优化器操作。默认情况下,优化程序将使用tf.trainable_variables()
中的所有变量。如果要将变量过滤到特定范围,可以使用tf.get_collection()
的可选scope
参数,如下所示:
optimizer = tf.train.AdagradOptimzer(0.01)
first_train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
"scope/prefix/for/first/vars")
first_train_op = optimizer.minimize(cost, var_list=first_train_vars)
second_train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
"scope/prefix/for/second/vars")
second_train_op = optimizer.minimize(cost, var_list=second_train_vars)
答案 1 :(得分:21)
var_list
:
W = tf.Variable(...)
C = tf.Variable(...)
Y_est = tf.matmul(W,C)
loss = tf.reduce_sum((data-Y_est)**2)
optimizer = tf.train.AdamOptimizer(0.001)
# You can pass the python object directly
train_W = optimizer.minimize(loss, var_list=[W])
train_C = optimizer.minimize(loss, var_list=[C])
我在这里有一个自包含的示例:https://gist.github.com/ahwillia/8cedc710352eb919b684d8848bc2df3a
答案 2 :(得分:16)
您可能想要考虑的另一个选项是您可以在变量上设置trainable = False。这意味着它不会被培训修改。
tf.Variable(my_weights, trainable=False)
答案 3 :(得分:1)
我不知道我的方法是否有缺点,但我用这个结构为自己解决了这个问题:
netstandard16
因此,如果do_gradient = <Tensor that evaluates to 0 or 1>
no_gradient = 1 - do_gradient
wrapped_op = do_gradient * original + no_gradient * tf.stop_gradient(original)
,值和渐变将会很好地流过,但如果do_gradient = 1
,则值将仅流过stop_gradient op,这将停止渐变回流。
对于我的场景,将do_gradient挂钩到random_shuffle张量的索引让我随机训练我的网络的不同部分。