在 TensorFlow 中分配 op:return 值是多少?

Assign op in TensorFlow: what is the return value?

我试图在 TensorFlow 中构建一个自动递增图。我认为 assign 操作可能适合它,但没有找到它的文档。

我假定此操作 returns 它的值——就像在类 C 语言中一样——并编写了以下代码:

import tensorflow as tf

counter = tf.Variable(0, name="counter")

one = tf.constant(1)
ten = tf.constant(10)

new_counter = tf.add(counter, one)
assign = tf.assign(counter, new_counter)
result = tf.add(assign, ten)

init_op = tf.initialize_all_variables()

with tf.Session() as sess:

  sess.run(init_op)

  for _ in range(3):

    print sess.run(result)

并且此代码有效。

问题是:这是预期的行为吗?为什么此处未记录分配操作:https://www.tensorflow.org/versions/0.6.0/api_docs/index.html

这是一个不推荐的操作吗?

tf.assign() 运算符是实现 Variable.assign() 方法的底层机制。它需要一个可变张量(具有tf.*_ref类型)和一个新值,return一个可变张量具有已更新为新值。提供 return 值是为了在后续读取之前更容易地对作业进行排序,但此功能没有很好的文档记录。一个例子有望说明:

v = tf.Variable(0)
new_v = v.assign(10)
output = v + 5  # `v` is evaluated before or after the assignment.

sess.run(v.initializer)

result, _ = sess.run([output, new_v.op])
print result  # ==> 10 or 15, depending on the order of execution.

v = tf.Variable(0)
new_v = v.assign(10)
output = new_v + 5  # `new_v` is evaluated after the assignment.

sess.run(v.initializer)

result = sess.run([output])
print result  # ==> 15

在您的代码示例中,数据流依赖项强制执行执行顺序 [read counter] -> new_counter = tf.add(...) -> tf.assign(...) -> [read output of assign] -> result = tf.add(...),这意味着语义是明确的。 但是,更新计数器的读取-修改-写入步骤效率有点低,并且当多个步骤运行并发时可能会出现意外行为。例如,访问同一个变量的多个线程可以观察到计数器向后移动(在旧值在新值之后写回的情况下)。

我建议您使用 Variable.assign_add() 来更新计数器,如下所示:

counter = tf.Variable(0, name="counter")

one = tf.constant(1)
ten = tf.constant(10)

# assign_add ensures that the counter always moves forward.
updated_counter = counter.assign_add(one, use_locking=True)

result = tf.add(updated_counter, ten)
# ...

tf.assign() 很好 documented in the latest versions 并且在项目中经常使用它。

This operation outputs "ref" after the assignment is done. This makes it easier to chain operations that need to use the reset value.

简而言之,它需要您的原始张量和一个新张量。它用新值和 returns 原始张量的引用更新张量的原始值。