tf.placeholder和tf.Variable有什么区别?

时间:2016-04-18 12:16:23

标签: tensorflow

我是TensorFlow的新手。我对tf.placeholdertf.Variable之间的区别感到困惑。在我看来,tf.placeholder用于输入数据,tf.Variable用于存储数据状态。这就是我所知道的。

有人可以向我详细解释他们的差异吗?特别是,何时使用tf.Variable以及何时使用tf.placeholder

14 个答案:

答案 0 :(得分:151)

简而言之,您可以将tf.Variable用于训练变量,例如模型的权重(W)和偏差(B)。

weights = tf.Variable(
    tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
                    stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))), name='weights')

biases = tf.Variable(tf.zeros([hidden1_units]), name='biases')

tf.placeholder用于提供实际的培训示例。

images_placeholder = tf.placeholder(tf.float32, shape=(batch_size, IMAGE_PIXELS))
labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))

这是您在培训期间提供培训示例的方式:

for step in xrange(FLAGS.max_steps):
    feed_dict = {
       images_placeholder: images_feed,
       labels_placeholder: labels_feed,
     }
    _, loss_value = sess.run([train_op, loss], feed_dict=feed_dict)

此培训将培训(修改)您的tf.variables

点击https://www.tensorflow.org/versions/r0.7/tutorials/mnist/tf/index.html了解详情。 (例子来自网页。)

答案 1 :(得分:60)

不同之处在于,使用tf.Variable时,必须在声明时提供初始值。使用tf.placeholder,您不必提供初始值,您可以在运行时使用feed_dict内的Session.run参数指定它

答案 2 :(得分:52)

由于Tensor计算由graphs组成,因此最好根据图解释这两者。

以简单线性回归WX + B = Y为例(其中W和B代表权重和偏差,X代表观察的输入,Y代表观察的输出)。显然,X和Y具有相同的性质(显性变量),它们与W和B(潜在变量)不同。 X和Y是样本的值(观察值),因此需要填充,而W和B是权重和偏差,变量(前一个值影响应该使用不同的X和Y对训练的图中的后者)。我们将不同的样本放置到占位符以训练变量

我们可以而且只需要保存或恢复 变量来保存或重建图表。 占位符主要是不同数据集的持有者(例如培训数据或测试数据),但变量在培训过程中经过培训并保持不变(预测结果)输入或映射样本的输入和输出[标签],直到您重新训练模型(使用不同或相同的样本通常通过dict填充占位符,例如{{1} },占位符也作为参数传递给设置模型)。

如果在训练过程中更改了占位符(添加或删除或更改形状等),您仍然可以重新加载检查点而无需任何其他修改。但是如果更改了已保存模型的变量,则应相应地调整检查点以重新加载它并继续训练(图中定义的所有变量都应在检查点中可用)。

总而言之,如果值来自样本(您已经拥有的观察值),您可以安全地制作一个占位符来保存它们,而如果您需要训练一个参数来使用变量(简单来说) put,设置变量以获取您想要使用TF自动获取的值。

有关详情,请参阅此simple and illustrating doc

答案 3 :(得分:33)

<强> TL; DR

<强>变量

  • 有关要学习的参数
  • 值可以从培训中获得
  • 需要初始值(通常是随机的)

<强>占位符

  • 为数据分配存储空间(例如供稿期间的图像像素数据)
  • 不需要初始值(但可以设置,请参阅tf.placeholder_with_default

答案 4 :(得分:32)

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

  

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

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

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

还存在其他差异:

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

答案 5 :(得分:14)

添加其他答案,他们也在Tensoflow网站的MNIST tutorial中解释得非常好:

  

我们通过操纵符号来描述这些交互操作   变量。让我们创建一个:

     

x = tf.placeholder(tf.float32, [None, 784])

     

x不是特定值。它是一个占位符,当我们向TensorFlow询问时,我们会输入一个值   运行计算。我们希望能够输入任意数量的MNIST   图像,每个平展成784维向量。我们代表   这是一个浮点数的二维张量,形状为[无,   784]。 (此处“无”表示维度可以是任意长度。)

     

我们还需要模型的权重和偏差。我们可以想象   将这些视为额外输入,但TensorFlow具有均匀性   更好的方法来处理它:VariableVariable是可修正的张量   它存在于TensorFlow的交互操作图中。有可能   使用甚至通过计算修改。用于机器学习   应用程序通常具有模型参数Variable s。

     

W = tf.Variable(tf.zeros([784, 10]))

     

b = tf.Variable(tf.zeros([10]))

     

我们通过提供Variable的初始值来创建这些tf.Variable   Variable:在这种情况下,我们将Wb初始化为张量满   零。由于我们要学习Wb,因此它并不重要   他们最初是什么。

答案 6 :(得分:8)

示例摘录:

import numpy as np
import tensorflow as tf

### Model parameters ###
W = tf.Variable([.3], tf.float32)
b = tf.Variable([-.3], tf.float32)

### Model input and output ###
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)

### loss ###
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares

### optimizer ###
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

### training data ###
x_train = [1,2,3,4]
y_train = [0,-1,-2,-3]

### training loop ###
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
  sess.run(train, {x:x_train, y:y_train})

正如名称所说占位符是承诺以后提供价值,即

变量只是训练参数(W(矩阵),b(偏差),与您在日常编程中使用的常规变量相同,培训师更新/修改每个运行/步骤。

虽然占位符并不需要任何初始值,但是当您创建xy时,TF并未分配任何内存,而是在以后您使用sess.run()feed_dict中为占位符提供内容,TensorFlow将为它们分配适当大小的内存(xy) - 这种无约束性允许我们提供任何内容数据的大小和形状。

简而言之

变量 - 是您希望教练(即GradientDescentOptimizer)在每个步骤后更新的参数。

占位符演示 -

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b  # + provides a shortcut for tf.add(a, b)

执行:

print(sess.run(adder_node, {a: 3, b:4.5}))
print(sess.run(adder_node, {a: [1,3], b: [2, 4]}))

产生输出

7.5
[ 3.  7.]

在第一种情况下,3和4.5将分别传递给ab,然后传递给adder_node输出7.在第二种情况下,有一个提要列表,第一步和第一步将被添加,接下来的3和4(ab)。

相关读物:

答案 7 :(得分:4)

将tensorflow中的Variable视为我们在编程语言中使用的常规变量。我们初始化变量,我们也可以稍后修改它。而placeholder不需要初始值。占位符只是分配内存块以供将来使用。稍后,我们可以使用feed_dict将数据提供给placeholder。默认情况下,placeholder具有不受约束的形状,允许您在会话中提供不同形状的张量。您可以通过传递可选参数-shape来制作约束形状,如下所示。

x = tf.placeholder(tf.float32,(3,4))
y =  x + 2

sess = tf.Session()
print(sess.run(y)) # will cause an error

s = np.random.rand(3,4)
print(sess.run(y, feed_dict={x:s}))

在进行机器学习任务时,大部分时间我们都不知道行数,但是(我们假设)我们知道功能或列的数量。在这种情况下,我们可以使用无。

x = tf.placeholder(tf.float32, shape=(None,4))

现在,在运行时,我们可以提供包含4列和任意行数的任何矩阵。

此外,占位符用于输入数据(它们是我们用来为模型提供的变量),其中变量是我们随时间训练的权重等参数。

答案 8 :(得分:4)

变量

TensorFlow变量是表示程序所控制的共享持久状态的最佳方法。变量通过tf.Variable类进行操作。在内部,tf.Variable存储持久张量。通过特定的操作,您可以读取和修改此张量的值。这些修改在多个tf.Session中可见,因此多个工作人员可以看到相同的tf.Variable值。使用前必须先初始化变量。

示例:

x = tf.Variable(3, name="x")
y = tf.Variable(4, name="y")
f = x*x*y + y + 2

这将创建一个计算图。可以在张量流会话中初始化变量(x和y)并评估函数(f),如下所示:

with tf.Session() as sess:
     x.initializer.run()
     y.initializer.run()
     result = f.eval()
print(result)
42

占位符

占位符是一个节点(与变量相同),其值可以在将来初始化。这些节点基本上在运行时输出分配给它们的值。可以使用tf.placeholder()类分配一个占位符节点,您可以向其提供参数,例如变量的类型和/或其形状。随着训练数据集不断变化,占位符广泛用于表示机器学习模型中的训练数据集。

示例:

A = tf.placeholder(tf.float32, shape=(None, 3))
B = A + 5

注意:尺寸的“无”表示“任何尺寸”。

with tf.Session as sess:
    B_val_1 = B.eval(feed_dict={A: [[1, 2, 3]]})
    B_val_2 = B.eval(feed_dict={A: [[4, 5, 6], [7, 8, 9]]})

print(B_val_1)
[[6. 7. 8.]]
print(B_val_2)
[[9. 10. 11.]
 [12. 13. 14.]]

参考文献:

  1. https://www.tensorflow.org/guide/variables
  2. https://www.tensorflow.org/api_docs/python/tf/placeholder
  3. O'Reilly:使用Scikit-Learn和Tensorflow进行动手机器学习

答案 9 :(得分:4)

与Tensorflow 2.0兼容的答案 tf.placeholder 不会在以下位置提供占位符的概念: Tensorflow 2.x (>= 2.0) 默认,因为“默认执行模式”是“急切执行”。

但是,如果在 Graph Mode Disable Eager Execution)中使用,我们可以使用它们。

2.x版中TF Placeholder的等效命令为 tf.compat.v1.placeholder

2.x版中TF变量的等效命令为 tf.Variable ,如果要将代码从1.x迁移到2.x,则等效命令为

tf.compat.v2.Variable

有关Tensorflow版本2.0的更多信息,请参阅此Tensorflow Page

有关从1.x到2.x版本的迁移的更多信息,请参考Migration Guide

答案 10 :(得分:3)

占位符:

  1. 占位符只是我们将在以后分配数据的变量。它允许我们创建我们的操作并构建我们的计算图,而不需要数据。在TensorFlow术语中,我们然后通过这些占位符将数据提供给图表。

  2. 初始值不是必需的,但可以使用tf.placeholder_with_default)

  3. 的默认值
  4. 我们必须在运行时提供价值,如:

    a = tf.placeholder(tf.int16) // initialize placeholder value
    b = tf.placeholder(tf.int16) // initialize placeholder value
    
    use it using session like :
    
    sess.run(add, feed_dict={a: 2, b: 3}) // this value we have to assign at runtime
    
  5. 变量:

    1. TensorFlow变量是表示共享的最佳方式, 由程序操纵的持久状态。
    2. 变量通过tf.Variable类进行操作。一个tf.Variable 表示一个张量,其值可以通过运行操作来改变。
    3. 示例:tf.Variable("Welcome to tensorflow!!!")

答案 11 :(得分:3)

Tensorflow使用三种类型的容器来存储/执行过程

  1. 常量:常量保存典型数据。

  2. 变量:将更改数据值,并使用cost_function等功能。

  3. 占位符:培训/测试数据将传递到图形中。

答案 12 :(得分:1)

考虑计算图。在这样的图中,我们需要一个输入节点将数据传递到图中,这些节点应在 tensorflow 中定义为占位符。

不要认为它是Python中的通用程序。您可以编写一个Python程序,并通过变量来完成其他答案中其他人解释的所有工作,但是对于tensorflow中的计算图,要将数据馈入图,则需要将这些点定义为占位符。

答案 13 :(得分:0)

对于TF V1:

  1. 常数为初始值,在计算中不会改变;

  2. 变量具有初始值,并且可以在计算中进行更改; (非常适合参数)

  3. 占位符没有初始值,并且在计算中不会更改。 (非常适合预测实例之类的输入)

对于TF V2,相同,但是他们尝试隐藏占位符(不建议使用图形模式)。