上下文
我正在使用Tensorflow 1.0在多个GPU上运行探测器模型。根据建议here,梯度是在多个GPU上单独计算的,并在CPU上进行平均。要在GPU塔上共享可训练变量(例如权重和偏差),使用reuse
打开tf.get_variable_scope().reuse_variables()
标志,如cifar10示例中所示。不同之处在于我使用的是AdamOptimizer
而不是GradientDescentOptimizer
。
问题
当我运行训练作业时,它打印出一个很长的堆栈跟踪并在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?
分析
查看源代码,我发现AdamOptimizer
在_create_slots()
方法中创建了许多零初始化的广告位,其中它调用了_zeros_slot()
。这会调用一个名为slot_creator
的单独模块(源代码已链接)。
在line 62
的{{1}}中,它使用slot_creator
。这在0.12中曾是variable_scope.get_variable()
。
我对变量范围的理解是,如果tf.Variable()
标志打开,variable_scope.get_variable()
将无法创建变量。有关源代码,请参阅here。
但Tensorflow创建者的cifar10示例似乎建议使用reuse
启用重用以跨GPU塔共享变量。这种情况发生在之前我们平均并应用渐变。看起来Tensorflow 1.0拒绝为tf.get_variable_scope().reuse_variables()
创建变量。
对于直接或间接调用AdamOptimizer
模块的所有优化器都会发生这种情况。
问题
作为快速修复,我在slot_creator
类中添加了一个自定义函数,以便在调用VariableScope
之前禁用_reuse
标志。但是,我确信强制opt.apply_gradients
标志仅设置为reuse
是有好处的。我不确定更好的解决方法是什么。有什么建议吗?
答案 0 :(得分:0)
在cifar10代码中,在grads = opt.compute_gradients(loss)
行前面移动tf.get_variable_scope().reuse_variables()
可以解决问题。