为什么在TensorFlow中需要“分配”?

时间:2019-02-21 14:39:23

标签: python tensorflow

我正在看一个示例here。我看到了以下操作顺序:

import tensorflow as tf

v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
inc_v1 = v1.assign(v1+1)
init_op = tf.global_variables_initializer()
s = tf.Session()
s.run(init_op)
s.run(inc_v1)

结果是:

array([1., 1., 1.], dtype=float32)

我不了解“分配”操作背后的逻辑。特别是,我用看起来更简单的东西代替了它:

import tensorflow as tf

v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
inc_v1 = v1 + 1
init_op = tf.global_variables_initializer()
s = tf.Session()
s.run(init_op)
s.run(inc_v1)

我得到了完全一样的输出。那么,为什么我们需要分配?

3 个答案:

答案 0 :(得分:2)

它采用原始张量和新张量,用新值更新张量的原始值,并返回原始张量的参考。看一下在Tensorboard上生成的图形:

操作assign返回对原始Tensor的引用:

Assign

在没有assign的情况下,仅创建另一个张量以添加恒定值:

No Assign

如果打印张量v1的求值(运行inc_v1之后),则输出[1. 1. 1.]作为操作的结果,它已重新分配给原始张量。在第二种情况下,它将保留为[0. 0. 0.]

答案 1 :(得分:2)

该示例确实不是很好的说明。重要的部分是assign将给定值保存到会话中的变量中,因此您可以稍后在下一次对run的调用中使用它。看到这里:

import tensorflow as tf

v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
inc_v1 = v1.assign(v1+1)
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init_op)
    sess.run(inc_v1)
    print(sess.run(v1))
    # [1. 1. 1.]
    sess.run(inc_v1)
    print(sess.run(v1))
    # [2. 2. 2.]

注意v1保存分配的值,因此在进一步调用run时可以使用它。现在比较:

import tensorflow as tf

v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
inc_v1 = v1+1
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init_op)
    sess.run(inc_v1)
    print(sess.run(v1))
    # [0. 0. 0.]
    sess.run(inc_v1)
    print(sess.run(v1))
    # [0. 0. 0.]

这里增量发生在一次调用run的过程中,但是其结果从未保存在任何地方,并且v1始终保持值为[0. 0. 0.]

变量很重要,因为TensorFlow中的大多数事情都是通过几个步骤完成的,例如神经网络中的每个批次。每个步骤都是对run的调用,重要的是,将步骤中的模型更改(例如,神经网络中权重的更新)保存用于下一步-否则,您将在的地方,永远不会离开起点!

答案 2 :(得分:0)

当您要分配一个非图形值时需要分配