tf.stop_gradient 和向优化器提供变量之间的 Tensorflow 差异?
Tensorflow difference between tf.stop_gradient and feed variables to optimizer?
我正在尝试在 self-supervised 学习 中训练模型。流程图如下所示:
让我们假设 N1
已经训练好了,我们只想训练 N2
。这是我当前的实现:
x_1 = tf.placeholder(tf.float32, [None, 128, 128, 1])
x_2 = tf.placeholder(tf.float32, [None, 128, 128, 1])
s_t1 = tf.stop_gradient(N1(x_1)) # treat s_t1 as a constant
s_t2_pred = N2(s_t1))
s_t2 = tf.stop_gradient(N1(x_2)) # treat s_t2 as a constant
loss = some_loss_function(s_t2, s_t2_pred)
train_op = tf.train.AdamOptimizer(lr).minimize(loss)
这样,我应该只优化 N2
。让我感到困惑的是,如果我使用以下代码,我会得到非常不同的结果(比上面的好得多):
# treat everything as a variable:
s_t1 = N1(x_1)
s_t2_pred = N2(s_t1)
s_t2 = N1(x_2)
loss = some_loss_function(s_t2, s_t2_pred)
var_list = take_all_variables_in_N2()
train_op = tf.train.AdamOptimizer(lr).minimize(loss, var_list)
我想知道第一个实现有什么问题。 tf.stop_gradient
的行为到底是什么(文档有点差)?这与第二种方法有何不同?
从实践角度semi-supervised学习:两者有什么区别?哪一个是正确的做法?
谢谢 :)
我在下面的评论中添加了一个可能的解决方案。我仍然很乐意收到更有经验的用户的任何反馈,并就在 tensorflow 中构建 self-supervised 学习问题的最佳方法分享一些意见。
再见,G.
我找到了我的问题的可能解决方案,我将其张贴在这里,以防有人觉得它有用。
显然,tf.stop_gradients()
只会阻止新梯度通过层反向传播,但是:如果我们有一个动量项(例如,当使用 Adam 或 RMSProp 时),这些层的变量仍然可以是由于过去累积的一些梯度(包含在动量项中)而更新。让我们看一下 SGD + Momentum 的简单案例;公式为:
w1 = w0 - a*grad(loss) - b*v0
其中w1
和w0
是时间0和1的权重,a
是学习率v0
是累积速度(过去的函数梯度)。使用 tf.stop_gradients()
相当于将第二项乘以零。那么,更新规则变为:
w1 = w0 - b*v0
例如我们还有一个可以更新权重的动量组件。
此问题的解决方法是将要更新的变量显式传递给优化器。例如:
var_list = take_all_variables_in_N2()
train_op = tf.train.AdamOptimizer(lr).minimize(loss, var_list)
参考文献:
[1] http://ruder.io/optimizing-gradient-descent/
[2]
我正在尝试在 self-supervised 学习 中训练模型。流程图如下所示:
让我们假设 N1
已经训练好了,我们只想训练 N2
。这是我当前的实现:
x_1 = tf.placeholder(tf.float32, [None, 128, 128, 1])
x_2 = tf.placeholder(tf.float32, [None, 128, 128, 1])
s_t1 = tf.stop_gradient(N1(x_1)) # treat s_t1 as a constant
s_t2_pred = N2(s_t1))
s_t2 = tf.stop_gradient(N1(x_2)) # treat s_t2 as a constant
loss = some_loss_function(s_t2, s_t2_pred)
train_op = tf.train.AdamOptimizer(lr).minimize(loss)
这样,我应该只优化 N2
。让我感到困惑的是,如果我使用以下代码,我会得到非常不同的结果(比上面的好得多):
# treat everything as a variable:
s_t1 = N1(x_1)
s_t2_pred = N2(s_t1)
s_t2 = N1(x_2)
loss = some_loss_function(s_t2, s_t2_pred)
var_list = take_all_variables_in_N2()
train_op = tf.train.AdamOptimizer(lr).minimize(loss, var_list)
我想知道第一个实现有什么问题。 tf.stop_gradient
的行为到底是什么(文档有点差)?这与第二种方法有何不同?
从实践角度semi-supervised学习:两者有什么区别?哪一个是正确的做法?
谢谢 :)
我在下面的评论中添加了一个可能的解决方案。我仍然很乐意收到更有经验的用户的任何反馈,并就在 tensorflow 中构建 self-supervised 学习问题的最佳方法分享一些意见。
再见,G.
我找到了我的问题的可能解决方案,我将其张贴在这里,以防有人觉得它有用。
显然,tf.stop_gradients()
只会阻止新梯度通过层反向传播,但是:如果我们有一个动量项(例如,当使用 Adam 或 RMSProp 时),这些层的变量仍然可以是由于过去累积的一些梯度(包含在动量项中)而更新。让我们看一下 SGD + Momentum 的简单案例;公式为:
w1 = w0 - a*grad(loss) - b*v0
其中w1
和w0
是时间0和1的权重,a
是学习率v0
是累积速度(过去的函数梯度)。使用 tf.stop_gradients()
相当于将第二项乘以零。那么,更新规则变为:
w1 = w0 - b*v0
例如我们还有一个可以更新权重的动量组件。
此问题的解决方法是将要更新的变量显式传递给优化器。例如:
var_list = take_all_variables_in_N2()
train_op = tf.train.AdamOptimizer(lr).minimize(loss, var_list)
参考文献:
[1] http://ruder.io/optimizing-gradient-descent/
[2]