在请求“ sess.run”变量的值时,为什么没有隐式控制依赖关系



我想了解是否存在以下行为的原因,可以用下面的代码段来复制。

当我请求sess.run返回Variable的值时,它返回的值并不取决于可能在返回之前更新所执行的变量的所有操作。

在此处的示例中,我正在测试用于将可变 a值复制到 b中的依赖项,然后以随机值重新分配a

该过程有效,但是第一个打印语句的结果是任意的(取决于任意处理顺序),第二印刷语句的结果是正确的。

我自然会期望张量 ab返回的值是所有计算的 end eend 的变量值,但事实并非如此。

有充分的理由不是,包括对作为sess.run的一部分要求的变量的隐式控制依赖关系?

import tensorflow as tf
a = tf.Variable(0.0)
b = tf.Variable(0.0)
r = tf.random_normal(shape=())
op_a2b = tf.assign(b, a)
with tf.control_dependencies([op_a2b]):
  op_r2a = tf.assign(a, r)
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
print(sess.run([a, b, r, op_r2a, op_a2b]))
print(sess.run([a, b]))

下面的结果。请注意,ab的值在sess.run的调用之间是不同的,尽管它们不变。这表明TensorFlow不能保证变量的返回值是在返回之前计算出的最后一件事。

[0.0, 0.0, 0.79926836, 0.79926836, 0.0]
[0.79926836, 0.0]

我认为有两件事要解释。

请记住,TensorFlow构建一个计算图,然后sess运行它。这样想:您要定义一个循环主体,然后sess每次呼叫一次迭代一次。在这种情况下,您不会期望a返回op_r2a的结果 - 因为a就像初始条件一样,而op_r2a就像循环主体中的更新。我认为这解决了您关于没有隐性控制依赖的充分理由的问题。

但是,您可以在代码块内使用tf.control_dependencies 强制它(这就是sess仍将返回"预分配"值的原因)。例如,在定义批处理规范时很有用。但是,您的with tf.control_dependencies无需做任何事情。您可以在with块外分配b <- a,然后分配a <- rwith块内部的内容不取决于外面的内容。

我更新了您的代码以尝试解释这一点。

import tensorflow as tf
# Define a graph, a_t <- r_{t-1}; b_t <- a_t
a = tf.Variable(0.0)
b = tf.Variable(1.0)
r = tf.random_normal(shape=())
update_a = tf.assign(a, r)
with tf.control_dependencies([update_a]):
    # JUST to illustrate tf.control_dependencies, 
    # make `a` take the value of `update_a`.
    update_b = tf.assign(b, a)
update_b_differently = tf.assign(b, update_a)
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
# Run it
print("Timestep 1:")
a0, b0, r1, a1, b1, bx = sess.run([a, b, r, update_a, update_b, 
                                  update_b_differently])
print("a_0 =", a0, "--> a_1 =", a1, "(= r_1 =", r1, ")")
print("b_0 =", b0, "--> b_1 =", b1, "(= a_1 =", a1, ")")
print("update_b =", b1, "= update_b_differently =", bx)
print("nTimestep 2 (Don't step up, just check initial conditions)")
a1_again, b1_again = sess.run([a, b])
print("a_1 =", a1_again, "is the initial condition for T.S. 2")
print("b_1 =", b1_again, "is the initial condition for T.S. 2")

输出

Timestep 1:
a_0 = 0.0 --> a_1 = 0.0190619 (= r_1 = 0.0190619 )
b_0 = 1.0 --> b_1 = 0.0190619 (= a_1 = 0.0190619 )
update_b = 0.0190619 = update_b_differently = 0.0190619
Timestep 2 (Don't step up, just check initial conditions)
a_1 = 0.0190619 is the initial condition for T.S. 2
b_1 = 0.0190619 is the initial condition for T.S. 2

通知我们分配给tf.Variable(0.0)并使用tf.control_dependencies在分配给update_b时将其持续,但是sess.run(a)仍然返回0。但是,当update_b退出with块时,a的新值持续使用update_b。也就是说,update_b取决于update_a更改a的值,但是tf.Variable(0.0)的值保持不变,直到下一个致电sess.run

最新更新