我是TensorFlow的新手.我对tf.placeholder
和之间的区别感到困惑tf.Variable
.在我看来,tf.placeholder
用于输入数据,并tf.Variable
用于存储数据的状态.这就是我所知道的.
有人可以向我详细解释他们的差异吗?特别是何时使用tf.Variable
以及何时使用tf.placeholder
?
简而言之,您可以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.(示例来自网页.)
不同之处在于,tf.Variable
您必须在声明时提供初始值.随着tf.placeholder
你没有提供一个初始值,你可以在运行时与指定它feed_dict
的参数内Session.run
由于Tensor计算由图形组成,因此最好根据图形来解释这两者.
例如,简单的线性回归WX + B = Y(其中W和B代表权重和偏差,X代表观察的输入,Y代表观察的输出).显然,X和Y具有相同的性质(显性变量),它们与W和B(潜在变量)不同.X和Y是样本的值(观察值),因此需要填充一个地方,而W和B是权重和偏差,图中的变量(前一个值影响后者)应使用不同的X和Y对.我们将不同的样本放置到占位符来训练变量.
我们只需要保存或恢复的变量保存或重建图.占位符主要是不同数据集的持有者(例如培训数据或测试数据),但变量在培训过程中经过培训并保持不变(预测输入结果或映射样本的输入和输出[标签])之后,直到您重新训练模型(例如,使用不同或相同的样本通常通过dict 填充占位符session.run(a_graph, dict={a_placeholder_name: sample_values})
,占位符也作为参数传递给设置模型).
如果在训练过程中更改模型的占位符(添加或删除或更改形状等),您仍然可以重新加载检查点而无需任何其他修改.但是如果更改了已保存模型的变量,则应相应地调整检查点以重新加载它并继续训练(图中定义的所有变量都应在检查点中可用).
总而言之,如果值来自样本(您已经拥有的观察值),您可以安全地制作一个占位符来保存它们,而如果您需要训练一个参数来控制变量(简单地放置,设置您想要的值的变量)自动使用TF).
有关详细信息,请参阅此简单和说明文档.
TL; DR
变量
用于学习参数
价值观可以从培训中获得
初始值是必需的(通常是随机的)
占位符
为数据分配存储空间(例如Feed中的图像像素数据)
初始值不是必需的(但可以设置,请参阅tf.placeholder_with_default
)
tf.Variable和tf.placeholder之间最明显的区别是
您使用变量来保存和更新参数.变量是包含张量的内存缓冲区.必须明确初始化它们,并且可以在训练期间和之后将其保存到磁盘.您可以稍后恢复已保存的值以锻炼或分析模型.
变量的初始化完成sess.run(tf.global_variables_initializer())
.另外,在创建变量时,您需要将Tensor作为其初始值传递给Variable()
构造函数,并在创建变量时始终知道其形状.
另一方面,您无法更新占位符.它们也不应该被初始化,但因为它们是一个承诺张量,你需要将值提供给它们sess.run(
.最后,与变量相比,占位符可能不知道形状.您既可以提供部分尺寸,也可以不提供任何尺寸.
还有其他差异:
可以在优化期间更新变量内的值
变量可以共享,也可以是不可训练的
变量内部的值可以在训练后存储
创建变量时,将3个操作添加到图形中(变量op,初始化操作符op,ops表示初始值)
占位符是一个函数,Variable是一个类(因此是一个大写)
当您在分布式环境中使用TF时,变量存储在特殊位置(参数服务器)并在工作者之间共享.
有趣的是,不仅可以喂养占位符.您可以将值提供给变量甚至是常量.
除了其他人的答案之外,他们还在Tensoflow网站上的MNIST 教程中解释得非常好:
我们通过操纵符号变量来描述这些交互操作.让我们创建一个:
x = tf.placeholder(tf.float32, [None, 784])
,
x
不是具体的价值.它是一个占位符,当我们要求TensorFlow运行计算时,我们将输入一个值.我们希望能够输入任意数量的MNIST图像,每个图像被平铺成784维向量.我们将其表示为浮点数的二维张量,形状为[None,784].(此处"无"表示尺寸可以是任意长度.)我们还需要模型的权重和偏差.我们可以想象将这些视为额外输入,但TensorFlow有更好的方法来处理它:
Variable
.AVariable
是一个可修改的张量,存在于TensorFlow的交互操作图中.它可以通过计算使用甚至修改.对于机器学习应用程序,通常具有模型参数Variable
s.
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
我们
Variable
通过给出tf.Variable
初始值来创建这些Variable
:在这种情况下,我们初始化两个W
和b
作为充满零的张量.既然我们要学习W
和b
,不要紧非常多他们最初是.
示例代码段:
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
并且y
TF没有分配任何内存时,相反,当你在sess.run()
使用中提供占位符时feed_dict
,TensorFlow将为它们分配适当大小的内存(x
和y
) - 这不受约束 - 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将分别传递给a
和b
,然后传递给adder_node输出7.在第二种情况下,有一个提要列表,第一步和第二步将被添加,接下来是3和4(a
和b
).
相关读物:
tf.placeholder doc.
tf.Variable doc.
可变VS占位符.
Tensorflow使用三种类型的容器来存储/执行过程
常数:常数保存典型数据。
variables:数据值将被更改,并带有相应的功能,例如cost_function。
占位符:培训/测试数据将传递到图形中。
将Variable
tensorflow视为我们在编程语言中使用的普通变量。我们初始化变量,以后也可以对其进行修改。虽然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列和任意行数的任何矩阵。
此外,占位符还用于输入数据(它们是我们用于馈送模型的变量的一种),其中,变量是诸如参数的参数,例如我们随时间训练的权重。
变数
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.]]
参考文献:
https://www.tensorflow.org/guide/variables
https://www.tensorflow.org/api_docs/python/tf/placeholder
O'Reilly:Scikit-Learn和Tensorflow的动手机器学习