tensorflow - tf.stop_gradient 和 feed 变量之间的 Tensorflow 差异优化器?
问题描述
让我们假设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
(文档有点差)?这与第二种方法有何不同?
从半监督学习的实际角度来看:两者有什么区别?哪一个是正确的方法?
谢谢 :)
我在下面的评论中添加了一个可能的解决方案。我仍然很乐意从更有经验的用户那里收到任何反馈,并就在 tensorflow 中构建自监督学习问题的最佳方法分享一些意见。
再见,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)
参考:
推荐阅读
- c++ - 尝试使用 clang++ v12 将两个 C++20 模块一起构建为一个模块
- docker - docker - 悬空(无)中间图像
- c# - 当用户没有在文本框中输入任何内容时,如何让代码使用不同的变量?
- graphql - 您如何定义 upsert(如果存在更新则插入)甚至使用 graphql 的更新?
- python - Apache Beam python fileio.WriteToFiles oversharding
- javascript - $.ajax() 不是一个函数,即使安装了普通的 jQuery
- uart - 初始化 Uart 引脚作为 PWM 输出
- record - Coq 中的记录子类型,请求的问题和参考资料
- python-3.x - selenium - python - 通过内部 HTML 查找元素
- python - 使用 SQLAlchemy 将 Flask WTForms 转换为 css 表单