不构建模型时占位符和变量之间是否存在差异?

时间:2016-12-23 01:39:37

标签: python python-3.x tensorflow

我试图了解TensorFlow中占位符和变量之间的区别:

X = tf.placeholder("float")
W = tf.Variable(rng.randn(), name="weight")

我还阅读了下面的Stack Overflow问题。我理解它们是模型输入时的区别。

  

InvalidArgumentError: You must feed a value for placeholder tensor Placeholder

但是,一般来说,如果我们不构建模型,tf.placeholder()tf.Variable()之间是否存在差异?

2 个答案:

答案 0 :(得分:21)

占位符

占位符用于将外部数据输入Tensorflow计算(图表外部的内容)。这是一些文档:(https://www.tensorflow.org/versions/r0.10/how_tos/reading_data/#feeding

  

TensorFlow的提要机制允许您将数据注入到任何Tensor中   计算图。因此,python计算可以直接提供数据   进入图表。

我个人会从占位符中抽取一个类比来读取标准输入。

x = raw_input()
X = tf.placeholder("float")

当您从标准输入读取时,您需要从外部源“注入数据”。与占位符相同。它允许您“注入”计算图外部的数据。

如果您正在培训学习算法,那么占位符的明确用例就是提供您的培训数据。训练数据不存储在计算图中。你打算如何进入图表?通过占位符注入它。一个占位符基本上就是你告诉图表“我还没有这个。但是当我要你跑的时候我会帮你的。”

可变

变量用于在图表中存储状态。它需要一个初始值。一个用例可以表示神经网络的权重或类似的东西。这是文档:(https://www.tensorflow.org/api_docs/python/tf/Variable

  

变量在调用run()时保持图中的状态。你添加   通过构造类的实例的图形变量   变量

     

Variable()构造函数需要变量的初始值,   它可以是任何类型和形状的张量。初始值定义   变量的类型和形状。施工后,类型和   变量的形状是固定的。可以使用以下值之一更改该值   分配方法。

我个人会在Tensorflow变量之间进行类比,并将Python中的变量分配给任何不依赖于外部内容的变量。例如,

# Tensorflow:
W = tf.Variable(rng.randn(), name="weight")

# Standard python:
w = 5
w = "hello"
w = [1, 2, 3, 4, 5]

W表示计算的某种结果。就像你必须在Python中初始化所有变量一样(你不能只运行命令x,你必须说x = ...something...),你必须初始化Tensorflow中的所有变量对象。

变量与占位符

在我看来,tf.Variabletf.placeholder之间的相关性不大。如果需要存储状态,请使用Variable。如果需要输入外部数据,可以使用placeholder

如果您没有构建模型,如果要插入在定义图形时不一定具有的外部数据,则仍应使用tf.placeholder。如果您没有构建模型,如果要在运行图形时存储某种计算结果,则仍需要tf.Variable

为什么两者都有?

我不是Tensorflow的专家,因此我只能推测为什么设计兼顾。

占位符和变量之间的一个巨大差异是占位符可以具有可变大小,但在构造图形时必须指定tf.Variable的形状。

可变大小的占位符感觉:也许我现在只想输入5号培训批次,但也许我想稍后增加批量大小。也许我提前不知道我将获得多少训练样例。

可变大小的变量没有意义:tf.Variable保存模型的学习参数,参数的数量不应改变。此外,Tensorflow扩展到分布式计算。如果你的整个计算过程中Variables的形状发生了变化,那么要在1000台计算机中正确分配它是非常困难的。

通常,您构建模型并且所有参数都是提前知道的,因此tf.Variable可能用于表示。 tf.placeholder可能适用于模型(或计算图)之外的所有其他内容,因此可以更灵活。

答案 1 :(得分:4)

tf.Variabletf.placeholder之间最明显的区别是

  

使用变量来保存和更新参数。变量是   包含张量的内存缓冲区。它们必须明确   初始化并可在培训期间和培训后保存到磁盘。您   以后可以恢复保存的值来锻炼或分析模型。

使用sess.run(tf.global_variables_initializer())初始化变量。另外,在创建变量时,需要将Tensor作为其初始值传递给Variable()构造函数,并在创建变量时始终知道其形状。

另一方面,您无法更新占位符。它们也不应该被初始化,但是因为它们是承诺张量,你需要将值提供给它们sess.run(<op>, {a: <some_val>})。最后,与变量相比,占位符可能不知道形状。您可以提供部分尺寸,也可以不提供任何内容。

还存在其他差异:

有趣的是,不仅可以喂养占位符。您可以将值提供给变量甚至是常量。