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

时间:2017-08-07 14:41:19

标签: python tensorflow

我想根据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)]]

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

我正在使用tensorflow 1.2

2 个答案:

答案 0 :(得分: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]

这是因为增量和条件的运行顺序不确定。最好明确依赖关系,所以如果你希望{<1}}在增量之后运行,你会这样做:

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])) 添加initialized_value。这确实不一致。此外,这种情况下的输出是:

'w1'

现在,让我感到恼火的是,增量的结果从两点开始。看起来增量运行的次数超过了预期。所以我觉得[0, 2] [1, 3] [0, 4] [1, 5] 以某种方式强制执行一次额外的第一次运行,这将是其奇怪行为的原因。

如果你想要相反,在增量之前让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])) &#39 {s} 'w1'了。这会产生:

initialized_value

我认为这些增量是有意义的。

答案 1 :(得分:0)

您应该使用placeholder_with_default

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