如何使用global_step来计算调用 tf.cond 的谓词?



我想根据global step的值执行不同的计算。这是我尝试做的一个最小示例:

import tensorflow as tf
global_step = tf.train.get_or_create_global_step()
incr_global_step = global_step.assign(global_step + 1)
w = tf.cond(tf.equal(tf.mod(global_step, 2), 0),
lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)),
lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for _ in range(4):
print(sess.run([w, incr_global_step]))

我收到以下错误:

FailedPreconditionError (see above for traceback): Attempting to use uninitialized value global_step
[[Node: global_step/read = Identity[T=DT_INT64, _class=["loc:@global_step"], _device="/job:localhost/replica:0/task:0/cpu:0"](global_step)]]

这是预期行为吗?如果是这样,我做错了什么?

我正在使用张量流 1.2

所以是的,这确实很奇怪。我能够通过以下修改运行您的代码:

import tensorflow as tf
global_step = tf.train.get_or_create_global_step()
incr_global_step = global_step.assign(global_step + 1)
w = tf.cond(tf.equal(tf.mod(global_step.initialized_value(), 2), 0),
lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)),
lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)).initialized_value())
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for _ in range(4):
print(sess.run([w, incr_global_step]))

请注意,我必须向global_step和变量添加initialized_value'w2'tf.cond,但不知何故'w1'(您也可以放置它,它会起作用,但显然,如果您不这样做,它将不会提交(。正如文档所提到的,此方法通常不是必需的,它只是提供变量的"视图",该视图保证在初始化使用。为什么tf.cond需要你使用它,为什么以这种不一致的方式,我不知道。

除此之外,请注意,运行代码的方式实际上不是确定性的。一般来说,你会得到这个:

[1, 1]
[0, 2]
[1, 3]
[0, 4]

但并非总是如此。这是我刚刚得到的输出:

[0, 1]
[0, 2]
[1, 3]
[0, 4]

这是因为增量和条件的运行顺序不是确定的。最好明确说明依赖项,因此如果您希望w在增量后运行,则应执行以下操作:

import tensorflow as tf
global_step = tf.train.get_or_create_global_step()
incr_global_step = global_step.assign(global_step + 1)
with tf.control_dependencies([incr_global_step]):
w = tf.cond(tf.equal(tf.mod(global_step.initialized_value(), 2), 0),
lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)).initialized_value(),
lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)).initialized_value())
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for _ in range(4):
print(sess.run([w, incr_global_step]))

令人惊讶的是,这也需要我为'w1'添加initialized_value。这确实不一致。此外,本例中的输出为:

[0, 2]
[1, 3]
[0, 4]
[1, 5]

现在,让我恼火的是,增量的结果从 2 开始。看起来增量的运行次数比预期的要多。所以我觉得tf.cond以某种方式强制执行一次额外的第一次运行,这将是其奇怪行为的原因。

如果你想要相反的,在增量之前运行w你可以做:

import tensorflow as tf
w = tf.cond(tf.equal(tf.mod(global_step.initialized_value(), 2), 0),
lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)),
lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)).initialized_value())
with tf.control_dependencies([w]):
incr_global_step = global_step.assign(global_step + 1)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for _ in range(4):
print(sess.run([w, incr_global_step]))

是的,我不再需要'w1'initialized_value了。这会产生:

[0, 1]
[1, 2]
[0, 3]
[1, 4]

我认为,这里的增量是有道理的。

你应该使用placeholder_with_default.

global_step = tf.placeholder_with_default(1, shape=[], name='global_step')

最新更新