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


290

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

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


7
直观地,您将需要相对于Variables的渐变,而不是相对于s的 渐变placeholder(必须始终提供其值)。
杨艺博

诸如cs231n.stanford.edu之类的课程可以帮助那些困惑的人。我很喜欢!显然还有其他人
内森

Answers:


175

简而言之,您可以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。(示例摘自网页。)


2
如果要在送入图像之前对其进行预处理,该怎么办?(例如重新调整对比度)。我现在需要一个变量吗?如果是这样,它对内存或速度有没有影响?
巴斯蒂安

1
在将数据输入到Tensorflow图(即网络)之前,您将进行任何预处理,因此从技术上讲,工作不需要Tensorflow的任何代码工具。例如,一个变量将是不必要的1.因为它是输入数据,将通过图中的tf.placeholders(不是变量)传递给它;并且2.在将其加载到当前通过网络传递给占位符之前进行预处理。
PaulG

只是想指出我对这个答案的欣赏程度。与这个问题相比,此答案的投票数要少得多,这一事实证明了人们可以做到即时满足,以及标签tensorflowdeep learning和标签如何流行AI
内森

70

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


63
-1。的确如此,但这没有抓住重点。更重要的区别是它们在TensorFlow中的作用。变量会随着时间的流逝而训练,占位符是输入数据,它们不会随模型训练而变化(例如输入图像和这些图像的类标签)。就像Sung Kim的答案所说,您可以在模型中使用变量来权重和偏差(尽管不限于此-对于样式转换,您可以随着时间的推移优化图像)。
克里斯·安德森

@ChrisAnderson我们可以说这个插图是错误的吗? youtu.be/MotG3XI2qSs?t=136
N0rA

@ChrisAnderson如果差异只是一个初始值,为什么要使用什么含义呢?
Goldname

1
@Goldname并不是要使用的“意思”,而是可能的和不可能的。它们是完全不同的对象。它们是不可互换的,并且区别不只是“一个需要初始值”。
克里斯·安德森

61

由于Tensor计算是由组成的,因此最好根据来解释两者。

以简单的线性回归为例

WX+B=Y

其中WB代表的权重和偏见,X对观测的投入和Y用于观测输出。

显然,XY具有相同的性质(清单变量),与WB(潜在变量)不同。XY是样本(观测值)的值,因此需要填充一个位置,而WB是权重和偏差,图中的变量(先前的值会影响后者)应使用不同XY成对的变量进行训练。我们将不同的样本放置到占位符上以训练变量

我们只需要保存或恢复变量(检查站)保存或重建与代码的图形。

占位符主要是不同数据集(例如训练数据或测试数据)的占位符。但是,变量会在训练过程中针对特定任务进行训练,即预测输入的结果或将输入映射到所需的标签。它们保持不变,直到您使用不同或相同的样本重新训练或微调模型以通过dict 填充到占位符为止。例如:

 session.run(a_graph, dict = {a_placeholder_name : sample_values}) 

占位符也作为参数传递给设置模型。

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

总而言之,如果值来自样本(您已经拥有的观测值),则可以安全地放置占位符,而如果需要训练参数,则可以使用变量(简而言之,为所需的值设置变量)自动使用TF)。

在一些有趣的模型中,例如样式转换模型,将对输入像素进行优化,并固定通常称为模型的变量,然后我们应将输入(通常是随机初始化)作为在该链接中实现的变量。

有关更多信息,请推断出此简单的说明性文档


38

TL; DR

变数

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

占位符

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

34

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


您可以使用变量来保存和更新参数。变量是包含张量的内存缓冲区。必须对它们进行显式初始化,并且可以在培训期间和之后将其保存到磁盘。您以后可以恢复保存的值以执行或分析模型。

变量的初始化是通过进行的sess.run(tf.global_variables_initializer())。同样在创建变量时,您需要将Tensor作为其初始值传递给Variable()构造函数,并且在创建变量时,您始终会知道其形状。


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


还有其他区别:

有趣的是,不仅可以喂占位符。您可以将值输入变量,甚至常量。


14

除了其他答案外,他们还在Tensoflow网站上的MNIST 教程中对此进行了很好的解释:

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

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

x不是特定值。它是一个占位符,当我们要求TensorFlow运行计算时将输入的值。我们希望能够输入任意数量的MNIST图像,每个图像均被展平为784维向量。我们将其表示为浮点数的二维张量,其形状为[None,784]。(此处无表示尺寸可以为任意长度。)

我们还需要模型的权重和偏见。我们可以想象将它们像其他输入一样对待,但是TensorFlow拥有更好的处理方式:Variable。A Variable是可修改的张量,位于TensorFlow的交互操作图中。计算可以使用甚至修改它。对于机器学习应用程序,通常将模型参数设为Variables。

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

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

我们Variable通过给出tf.Variable的初始值来创建这些Variable:在这种情况下,我们将初始化为,W并将b其初始化为零的张量。由于我们将学习Wb,所以它们最初的含义并不重要。


嗨,谢谢您的回答!在您给出的示例中,我们具有xshape [batch size, features],权重从输入到大小的第一层[features, hidden units]以及bias [hidden units]。所以我的问题是:我们如何将它们相乘?如果我们这样做,tf.matmul(x, w)那么我们将得到,[batch size, hidden units]而我们将无法b实现,因为它已定型[hidden units]
Euler_Salter

1
M.Gorner在他的幻灯片放映中解释了所有这些内容,“无需博士学位即可学习TensorFlow和深度学习”。比我在此评论中做的要好。因此,请允许我参考此幻灯片: docs.google.com/presentation/d/…–
tagoma

11

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

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

  2. variables:数据值将被更改,并带有相应的功能,例如cost_function。

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


10

示例片段:

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(偏差)),与您在日常编程中使用的普通变量相同,培训员会在每次运行/步骤中对其进行更新/修改。

尽管占位符不需要任何初始值,但当您创建x并且yTF不会分配任何内存时,而是稍后在您sess.run()使用using 喂占位符时feed_dict,TensorFlow会为其分配适当大小的内存(xy)-这种不受限制的ness允许我们提供任何大小和形状的数据。


简而言之

变量 -是您希望训练师(即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,然后传递到输出7的adder_node。在第二种情况下,有一个供稿列表,第一步将添加步骤1和2,接下来是第3步和第4步(ab)。


相关读物:


7

变数

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进行动手机器学习

6

Variabletensorflow中的正常变量视为我们在编程语言中使用的普通变量。我们初始化变量,以后也可以对其进行修改。虽然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}))

在执行机器学习任务时,大多数时候我们不知道行数,但是(假设)我们知道功能或列数。在这种情况下,我们可以使用None。

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

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

此外,占位符还用于输入数据(它们是我们用于馈送模型的变量的一种),其中,变量是参数,例如我们随时间训练的权重。


4

占位符:

  1. 占位符只是一个变量,稍后我们将为其分配数据。它使我们无需数据即可创建操作并构建计算图。在TensorFlow术语中,我们然后通过这些占位符将数据输入到图中。

  2. 初始值不是必需的,但可以具有默认值 tf.placeholder_with_default)

  3. 我们必须在运行时提供价值,例如:

    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

变量:

  1. TensorFlow变量是表示程序所控制的共享持久状态的最佳方法。
  2. 变量通过tf.Variable类进行操作。tf.Variable表示一个张量,其值可以通过在其上运行ops进行更改。

范例: tf.Variable("Welcome to tensorflow!!!")


3

Tensorflow 2.0兼容的答案:占位符的概念tf.placeholderTensorflow 2.x (>= 2.0)默认情况下不可用,因为默认执行模式为急切执行。

但是,如果用于Graph ModeDisable Eager Execution),我们可以使用它们。

版本2.x中TF占位符的等效命令为tf.compat.v1.placeholder

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

tf.compat.v2.Variable

请参考此Tensorflow页面以获取有关Tensorflow版本2.0的更多信息。

有关从1.x到2.x版本的迁移的更多信息,请参阅《迁移指南》


2

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.