带有tf.control_dependencies的同一代码的不同结果

时间:2019-10-29 12:28:48

标签: tensorflow variables session

我两次运行一段代码,并得到两个不同的结果

代码:

import tensorflow as tf
x = tf.placeholder(tf.int32, shape=[], name='x')
y = tf.Variable(2, dtype=tf.int32)
assign_op = tf.assign(y, y + 1)
out = x * y
with tf.control_dependencies([assign_op]):
    out_ = out+2
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(3):
        print('output:', sess.run(out_, feed_dict={x: 1}))

第一个输出:

output: 4
output: 5
output: 6

第二个输出:

output: 4
output: 6
output: 6

有人可以解释为什么会发生吗?

2 个答案:

答案 0 :(得分:1)

问题是执行操作的顺序存在不确定性。 out_始终等于out + 2,在这种情况下,control_dependencies块没有任何区别。问题是out的值是多少。在某些情况下,out会在y更新之前进行计算,而在其他情况下,则是在更新之后进行计算,因此您可以获得4, 5, 65, 6, 7及其之间的所有内容。

如果要确保在更新{em> out之后计算y,可以执行以下操作:

import tensorflow as tf
x = tf.placeholder(tf.int32, shape=[], name='x')
y = tf.Variable(2, dtype=tf.int32)
y_new = tf.assign(y, y + 1)  # tf.assign always returns the updated value
out = x * y_new
out_ = out + 2

这将始终打印序列5, 6, 7

如果要确保在更新{em> out之前计算y,可以执行以下操作:

import tensorflow as tf
x = tf.placeholder(tf.int32, shape=[], name='x')
y = tf.Variable(2, dtype=tf.int32)
out = x * y
with tf.control_dependencies([out]):
    y_new = tf.assign(y, y + 1)
out_ = out + 2

但是,在这种情况下,评估out_将不会更新y(因为out_并不取决于更新)。如果您仍然希望获得这种效果(否则您将始终在输出中得到4),可以执行以下操作:

import tensorflow as tf
x = tf.placeholder(tf.int32, shape=[], name='x')
y = tf.Variable(2, dtype=tf.int32)
out = x * y
with tf.control_dependencies([out]):
    y_new = tf.assign(y, y + 1)
# Force update y every time out is evaluated
with tf.control_dependencies([y_new]):
    out = tf.identity(out)
out_ = out + 2

总是显示序列4, 5, 6

答案 1 :(得分:1)

Tensorflow不会像普通的python程序那样记录操作创建的顺序,而是仅跟踪其依赖关系,因此仅保证operation/op的所有依赖关系在op执行之前已执行。

因此,在某些情况下,out_可以在更新y的值之后进行更新,而在其他情况下,由于y仅具有一个{对out_。ie的传递依赖它取决于yy变量。