我试图在TensorFlow中构建一个自动增量图。我认为assign
op可能适用于此,但没有找到它的文档。
我假设这个op在类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
这是不推荐的操作吗?
答案 0 :(得分:16)
tf.assign()
运算符是实现Variable.assign()
方法的基础机制。它需要可变张量(带tf.*_ref
类型)和一个新值,并返回已使用新值更新的可变张量。提供返回值是为了便于在后续读取之前订购赋值,但此功能没有详细记录。一个例子有望说明:
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)
# ...
答案 1 :(得分:4)
tf.assign()
非常documented in the latest versions,并且在项目中经常使用。
分配完成后,此操作输出“ref”。这使得 更容易链接需要使用重置值的操作。
用简单的话来说,它需要你的原始张量和新的张量。它使用新值更新张量的原始值,并返回原始张量的参考值。