Context
我正在使用Tensorflow 1.0在多个GPU上研究探测器模型 . 正如建议here,梯度是在多个GPU上单独计算的,并在CPU上取平均值 . 要在GPU塔之间共享可训练变量(例如权重和偏差), reuse
标志将使用 tf.get_variable_scope().reuse_variables()
打开,如cifar10示例中所示 . 区别在于我使用 AdamOptimizer
而不是 GradientDescentOptimizer
.
Problem
当我运行训练作业时,它打印出一个长堆栈跟踪并在 opt.apply_gradients()
处引发以下错误:
ValueError: Variable conv1_1/kernel/Adam/ does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=None in VarScope?
Analysis
查看源代码,我发现 AdamOptimizer
在 _create_slots()
方法中创建了许多零初始化的插槽,其中它调用 _zeros_slot()
. 这会调用一个名为slot_creator的单独模块(源代码已链接) .
In line 62 of the slot_creator, it uses variable_scope.get_variable(). This used to be tf.Variable() in 0.12.
我对变量范围的理解是 variable_scope.get_variable()
无法创建变量 if reuse flag is on`. See here for source code.
但Tensorflow创建者的cifar10示例似乎建议使用 tf.get_variable_scope().reuse_variables()
启用重用以跨GPU塔共享变量 . 这发生 before 我们平均并应用渐变 . 看起来Tensorflow 1.0拒绝为 AdamOptimizer
创建变量 .
对于直接或间接调用 slot_creator
模块的所有优化器都会发生这种情况 .
Question
作为快速修复,我在 VariableScope
类中添加了一个自定义函数,以便在调用 opt.apply_gradients
之前禁用 _reuse
标志 . 但是,我确信强制 reuse
标志仅设置为 True
是有好处的 . 我不确定更好的解决方法是什么 . 有什么建议?
1 回答
在cifar10代码中,在
tf.get_variable_scope().reuse_variables()
行前移动grads = opt.compute_gradients(loss)
应该可以解决问题 .