使用占位符和变量
占位符和变量是在 TensorFlow 中使用计算图的关键工具。我们必须了解它们之间的区别以及何时最好地利用它们对我们有利。
做好准备
与数据最重要的区别之一是它是占位符还是变量。变量是算法的模型参数,TensorFlow 跟踪如何更改这些参数以优化算法。占位符是允许您提供特定类型和形状的数据的对象,或者取决于计算图的结果,例如计算的预期结果。
操作步骤
创建变量的主要方法是使用Variable()
函数,该函数将张量作为输入并输出变量。这只是声明,我们仍然需要初始化变量。初始化是将变量与相应方法放在计算图上的内容。以下是创建和初始化变量的示例:
my_var = tf.Variable(tf.zeros([2,3]))
sess = tf.Session()
initialize_op = tf.global_variables_initializer()
sess.run(initialize_op)
要在创建和初始化变量后查看计算图是什么样的,请参阅此秘籍的以下部分。占位符只是保持数据的位置以输入图。占位符从会话中的feed_dict
参数获取数据。要将占位符放入图中,我们必须对占位符执行至少一个操作。在下面的代码片段中,我们初始化图,将x
声明为占位符(预定义大小),并将y
定义为x
上的标识操作,它只返回x
。然后,我们创建数据以提供给x
占位符并运行身份操作。代码如下所示,结果图如下:
sess = tf.Session()
x = tf.placeholder(tf.float32, shape=[2,2])
y = tf.identity(x)
x_vals = np.random.rand(2,2)
sess.run(y, feed_dict={x: x_vals})
# Note that sess.run(x, feed_dict={x: x_vals}) will result in a self-referencing error.
值得注意的是,TensorFlow 不会在 Feed 字典中返回自引用占位符。换句话说,在下图中运行
sess.run(x, feed_dict={x: x_vals})
将返回错误。
工作原理
将变量初始化为零张量的计算图如下图所示:
图 1:变量
在这里,我们只用一个变量就可以看到计算图的详细信息,并将其全部初始化为零。灰色阴影区域是对所涉及的操作和常数的非常详细的视图。细节较少的主要计算图是右上角灰色区域之外的较小图。有关创建和可视化图的更多详细信息,请参阅第 10 章的第一部分,将 TensorFlow 转换为生产。类似地,可以在下图中看到将 NumPy 数组送入占位符的计算图:
图 2:初始化占位符的计算图
灰色阴影区域是对所涉及的操作和常数的非常详细的视图。细节较少的主要计算图是右上角灰色区域之外的较小图。
更多
在计算图运行期间,我们必须告诉 TensorFlow 何时初始化我们创建的变量。虽然每个变量都有一个initializer
方法,但最常用的方法是使用辅助函数,即global_variables_initializer()
。此函数在图中创建一个初始化我们创建的所有变量的操作,如下所示:
initializer_op = tf.global_variables_initializer()
但是如果我们想根据初始化另一个变量的结果来初始化变量,我们必须按照我们想要的顺序初始化变量,如下所示:
sess = tf.Session()
first_var = tf.Variable(tf.zeros([2,3]))
sess.run(first_var.initializer)
second_var = tf.Variable(tf.zeros_like(first_var))
# 'second_var' depends on the 'first_var'
sess.run(second_var.initializer)