tf.placeholder 和 tf.Variable 有啥区别?
Posted
技术标签:
【中文标题】tf.placeholder 和 tf.Variable 有啥区别?【英文标题】:What's the difference between tf.placeholder and tf.Variable?tf.placeholder 和 tf.Variable 有什么区别? 【发布时间】:2016-08-10 04:14:42 【问题描述】:我是 TensorFlow 的新手。我对tf.placeholder
和tf.Variable
之间的区别感到困惑。在我看来,tf.placeholder
用于输入数据,tf.Variable
用于存储数据的状态。这就是我所知道的。
谁能更详细地向我解释他们之间的差异?特别是什么时候用tf.Variable
,什么时候用tf.placeholder
?
【问题讨论】:
直观地说,您需要相对于Variable
s 的渐变,而不是placeholder
s(必须始终提供其值)。
像cs231n.stanford.edu 这样的课程可以帮助那些困惑的人。我很喜欢!显然还有其他的
【参考方案1】:
简而言之,您可以将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 上查看更多信息。 (示例来自网页。)
【讨论】:
如果我想在输入图像之前对其进行预处理怎么办? (例如,重新调整对比度)。我现在需要一个变量吗?如果是这样,它对内存或速度有影响吗? 您所做的任何预处理都将在将数据输入到 Tensorflow 图(即网络)之前进行,因此从技术上讲,这项工作不需要任何来自 Tensorflow 的代码工具。例如,一个变量是不必要的 1. 因为它是输入数据,它通过图形中的 tf.placeholders(不是变量)传递 2. 预处理发生在它被加载到当前通过网络的占位符之前. 只是想说明我多么欣赏这个答案。对这个答案的赞成票比对这个问题的赞成票要少得多,这一事实表明人们可以即时满足,以及tensorflow
、deep learning
和AI
等时尚标签的流行程度。
所以这意味着,tf.Variable
=> 反向传播时更新; tf.placeholder
=> 反向传播时不更新。对吗?【参考方案2】:
不同之处在于tf.Variable
在声明它时必须提供一个初始值。使用tf.placeholder
,您不必提供初始值,您可以在运行时使用feed_dict
参数在Session.run
中指定它
【讨论】:
-1。虽然是真的,但这没有抓住重点。更重要的区别是它们在 TensorFlow 中的角色。变量会随着时间的推移进行训练,占位符是不会随着模型训练而改变的输入数据(如输入图像和这些图像的类标签)。就像 Sung Kim 的回答所说,您在模型中使用变量来表示权重和偏差(尽管不限于此 - 对于风格转移,您会随着时间的推移优化图像)。 @ChrisAnderson 我们可以说这个插图是错误的吗?! youtu.be/MotG3XI2qSs?t=136 @ChrisAnderson 为什么它的用途很重要,如果差异只是需要一个初始值? @Goldname 这不是它的“本意”用途——它是可能的和不可能的。它们是完全不同的对象。它们不可互换,并且差异不仅仅是“需要一个初始值”。【参考方案3】:由于张量计算由graphs 组成,因此最好用图形来解释这两者。
以简单的线性回归为例
WX+B=Y
其中W
和B
代表权重和偏差,X
代表观察的输入,Y
代表观察的输出。
显然X
和Y
具有相同的性质(显式变量),不同于W
和B
(潜在变量)的性质。 X
和 Y
是样本(观察值)的值,因此需要填充位置,而 W
和 B
是权重和偏差,变量(前面的值会影响后面的值)应该使用不同的 X
和 Y
对进行训练。我们将不同的样本放置到 Placeholders 以训练 Variables。
我们只需要保存或恢复 变量(在检查点处)即可使用代码保存或重建图表。
占位符主要是不同数据集(例如训练数据或测试数据)的持有者。但是,变量在特定任务的训练过程中被训练,即预测输入的结果或将输入映射到所需的标签。在您使用不同或相同的样本重新训练或微调模型以经常通过 dict 填充 Placeholders 之前,它们保持不变。例如:
session.run(a_graph, dict = a_placeholder_name : sample_values)
占位符 也作为参数传递给设置模型。
如果您在训练过程中更改模型的占位符(添加、删除、更改形状等),您仍然可以重新加载检查点而无需进行任何其他修改。但是如果保存的模型的变量发生了变化,您应该相应地调整检查点以重新加载它并继续训练(图中定义的所有变量都应该在检查点中可用)。
总而言之,如果这些值来自样本(您已经拥有的观察结果),您可以安全地制作一个占位符来保存它们,而如果您需要一个参数来进行训练,则使用 变量(简单地说将 Variables 设置为您想要使用 TF 自动获取的值)。
在一些有趣的模型中,例如a style transfer model,输入像素将被优化并且通常称为模型变量是固定的,然后我们应该将输入(通常随机初始化)作为该链接中实现的变量.
更多信息请参考此simple and illustrating doc。
【讨论】:
【参考方案4】:TL;DR
变量
用于学习的参数 值可以从训练中获得 需要初始值(通常是随机的)占位符
为数据分配的存储空间(例如在馈送期间用于图像像素数据) 初始值不是必需的(但可以设置,参见tf.placeholder_with_default
)
【讨论】:
【参考方案5】:tf.Variable 和tf.placeholder 最明显的区别在于
您使用变量来保存和更新参数。变量是 包含张量的内存缓冲区。它们必须明确 初始化,可以在训练期间和训练后保存到磁盘。你 以后可以恢复保存的值来练习或分析模型。
变量的初始化是使用sess.run(tf.global_variables_initializer())
完成的。此外,在创建变量时,您需要将张量作为其初始值传递给 Variable()
构造函数,并且当您创建变量时,您始终知道它的形状。
另一方面,您无法更新占位符。它们也不应该被初始化,但因为它们承诺有一个张量,所以你需要将值输入它们sess.run(<op>, a: <some_val>)
。最后,与变量相比,占位符可能不知道形状。您可以提供部分尺寸,也可以什么都不提供。
还有其他区别:
变量内的值可以在优化期间更新 变量可以是shared,也可以是non-trainable 变量内的值可以在训练后存储 创建变量时,3 ops are added to a graph(变量操作,初始化操作,初始值操作) placeholder is a function, Variable is a class(因此是大写) 当您在分布式环境中使用 TF 时,变量存储在一个特殊的位置 (parameter server) 并在工作人员之间共享。有趣的部分是不仅可以输入占位符。您可以将值提供给变量,甚至提供给常量。
【讨论】:
【参考方案6】:添加到其他人的答案中,他们也在 Tensoflow 网站上的 MNIST tutorial 中很好地解释了这一点:
我们通过操纵符号来描述这些交互操作 变量。让我们创建一个:
x = tf.placeholder(tf.float32, [None, 784])
,
x
不是特定值。它是一个占位符,当我们要求 TensorFlow 运行计算。我们希望能够输入任意数量的 MNIST 图像,每个都被展平成一个 784 维的向量。我们代表 这是浮点数的二维张量,形状为 [None, 784]。 (这里的 None 表示维度可以是任意长度。)我们还需要模型的权重和偏差。我们可以想象 将这些视为额外的输入,但 TensorFlow 有一个偶数 更好的处理方法:
Variable
。Variable
是一个可修改的张量 它存在于 TensorFlow 的交互操作图中。有可能 被计算使用甚至修改。用于机器学习 应用中,模型参数一般为Variable
s。
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
我们通过赋予
tf.Variable
的初始值来创建这些Variable
sVariable
:在这种情况下,我们将W
和b
都初始化为满张量 的零。既然我们要学习W
和b
,那就无所谓了 和它们最初的样子差不多。
【讨论】:
您好,谢谢您的回答!在您给出的示例中,我们有x
形状为 [batch size, features]
,权重从输入到大小为 [features, hidden units]
的第一层和偏差 [hidden units]
。所以我的问题是:我们如何将它们相乘?如果我们做tf.matmul(x, w)
,那么我们将得到[batch size, hidden units]
,我们不能b
,因为它的形状是[hidden units]
M.Gorner 在他的幻灯片“学习 TensorFlow 和深度学习,无需博士学位”中解释了这一切。比我在此评论中所做的更好。所以,请允许我参考这张幻灯片:docs.google.com/presentation/d/…【参考方案7】:
Tensorflow 使用三种类型的容器来存储/执行流程
常量:常量保存典型数据。
变量:数据值会随着cost_function等函数发生变化。
占位符:训练/测试数据将传入图表。
【讨论】:
【参考方案8】:示例 sn-p:
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
(matrix), b
(bias) 与您在日常编程中使用的正常变量相同,培训师会更新/修改这些变量每次运行/步骤。
虽然 placeholder 不需要任何初始值,但当您创建 x
和 y
时,TF 不会分配任何内存,而是稍后当您在 @987654329 中提供占位符时@ 使用 feed_dict
,TensorFlow 将为它们分配适当大小的内存(x
和 y
)——这种不受约束的特性允许我们提供任何大小和形状的数据。
简而言之:
变量 - 是您希望训练器(即 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 将分别传递给 a
和 b
,然后到 adder_node 输出 7。在第二种情况下,有一个提要列表,第一步和 2 将被添加,接下来的 3 和4(a
和 b
)。
相关阅读:
tf.placeholder 博士。 tf.Variable 博士。 Variable VS placeholder。【讨论】:
【参考方案9】:变量
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) 可以在 tensorflow 会话中初始化,函数 (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.]]
参考资料:
-
https://www.tensorflow.org/guide/variables
https://www.tensorflow.org/api_docs/python/tf/placeholder
O'Reilly:使用 Scikit-Learn 和 Tensorflow 进行机器学习实践
【讨论】:
【参考方案10】:将 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))
在执行机器学习任务时,大多数时候我们不知道行数,但(假设)我们知道特征或列的数量。在这种情况下,我们可以使用 None。
x = tf.placeholder(tf.float32, shape=(None,4))
现在,在运行时,我们可以输入任何 4 列和任意行数的矩阵。
此外,占位符用于输入数据(它们是我们用来为模型提供数据的一种变量),其中变量是我们随时间训练的权重等参数。
【讨论】:
【参考方案11】:占位符:
占位符只是一个变量,我们将在以后为其分配数据。它允许我们创建我们的操作并构建我们的计算图,而不需要数据。在 TensorFlow 术语中,我们然后通过这些占位符将数据输入到图表中。
初始值不是必需的,但可以有默认值tf.placeholder_with_default)
我们必须在运行时提供价值,例如:
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
变量:
-
TensorFlow 变量是表示共享的最佳方式,
由您的程序操纵的持久状态。
变量通过 tf.Variable 类进行操作。一个 tf 变量
表示一个张量,其值可以通过对其运行操作来更改。
例如:tf.Variable("Welcome to tensorflow!!!")
【讨论】:
【参考方案12】:Tensorflow 2.0 兼容答案:占位符的概念,tf.placeholder
默认在 Tensorflow 2.x (>= 2.0)
中不可用,因为默认执行模式是急切执行。
但是,如果在 Graph Mode
(Disable Eager Execution
) 中使用,我们可以使用它们。
2.x 版本中 TF 占位符的等效命令是 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。
【讨论】:
【参考方案13】:想一个计算图。在这样的图表中,我们需要一个输入节点来将我们的数据传递给图表,这些节点应该在 tensorflow 中定义为占位符。
不要认为是 Python 中的通用程序。您可以编写一个 Python 程序并执行其他人在其他答案中仅通过变量解释的所有内容,但对于 tensorflow 中的计算图,要将您的数据提供给图表,您需要将这些节点定义为占位符。
【讨论】:
【参考方案14】:对于 TF V1:
常数是有初始值的,在计算中不会改变;
变量是有初始值的,在计算中可以改变; (非常适合参数)
占位符没有初始值,在计算中不会改变。 (非常适合预测实例等输入)
对于 TF V2,相同,但他们尝试隐藏占位符(不首选图形模式)。
【讨论】:
以上是关于tf.placeholder 和 tf.Variable 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章