tf和tf的区别是什么?占位符和tf.Variable?

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

谁能给我详细解释一下他们的不同之处吗?特别是,什么时候使用tf.Variable,什么时候使用tf.placeholder?

112741 次浏览

简而言之,你使用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,你不需要提供初始值,你可以在运行时用Session.run中的feed_dict参数指定它

由于张量计算由组成,所以最好用图来解释这两者。

以简单的线性回归为例

WX+B=Y

其中WB代表权重和偏差,X代表观测值的输入,Y代表观测值的输出。

显然,XY具有相同的性质(显变量),而不同于WB(潜变量)。XY是样本(观测值)的值,因此需要一个Y0,而WB是图中的权重和偏置,Y1(前面的值影响后者)应该使用不同的XY对进行训练。我们将不同的样本放置到Y2中来训练Y1。

我们只需要保存或恢复 变量(在检查点)来保存或用代码重新构建图形。

占位符主要是不同数据集的持有者(例如训练数据或测试数据)。然而,变量在训练过程中被训练为特定的任务,即预测输入的结果或将输入映射到所需的标签。它们保持不变,直到你使用不同或相同的样本重新训练或微调模型,通常通过字典填充到占位符中。例如:

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

占位符也作为参数来设置模型。

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

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

在一些有趣的模型中,如风格迁移模型,输入像素将被优化,通常称为模型变量是固定的,然后我们应该将输入(通常是随机初始化的)作为在该链接中实现的变量。

欲了解更多信息,请推断到这个简单明了的文档

加上其他人的答案,他们也在Tensoflow网站上的MNIST教程中解释得很好:

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

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

x不是一个特定的值。它是一个占位符,一个我们在请求TensorFlow时输入的值 运行一个计算。我们希望能够输入任意数量的MNIST 图像,每一张都被平化为784维的矢量。我们代表 这是一个二维的浮点数张量,形状为[None, 784]。(这里的None表示维度可以是任何长度)

我们还需要模型的权重和偏差。我们可以想象 把这些当成额外的输入,但是TensorFlow有一个偶数 更好的处理方法:VariableVariable是一个可修改张量 它存在于TensorFlow的交互操作图中。它可以是 被计算所使用甚至修改。对于机器学习 在应用程序中,模型参数通常为Variables.

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

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

我们通过给tf.Variable的初始值来创建这些__abc0 Variable:在这种情况下,我们将Wb初始化为满张量 0。因为我们将学习Wb,所以这并不重要

示例代码片段:

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时不分配任何内存,相反,当你稍后使用feed_dictsess.run()中提供占位符时,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。在第二种情况下,有一个提要列表,第一步1和2将被添加,接下来的3和4 (ab)。


相关阅读:

博士TL;

变量

  • 为了学习参数
  • 价值观可以从培训中获得
  • 初始值是必需的(通常是随机的)

占位符

  • 为数据分配存储(例如在馈送期间用于图像像素数据)
  • 初始值不是必需的(但可以设置,参见tf.placeholder_with_default)

特遣部队。变量tf.placeholder之间最明显的区别是


你使用变量来保存和更新参数。变量是 包含张量的内存缓冲区。它们必须明确 已初始化,可以在培训期间和培训结束后保存到磁盘。你

变量的初始化是用sess.run(tf.global_variables_initializer())完成的。另外,在创建变量时,你需要将一个Tensor作为它的初始值传递给Variable()构造函数,当你创建一个变量时,你总是知道它的形状。


另一方面,您不能更新占位符。它们也不应该被初始化,但因为它们是有一个张量的承诺,你需要将值输入到它们sess.run(<op>, {a: <some_val>})。最后,与变量相比,占位符可能不知道形状。您可以提供部分维度,也可以什么都不提供。


还有其他区别:

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

占位符:

  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
    

Variable :

  1. A TensorFlow variable is the best way to represent shared, persistent state manipulated by your program.
  2. Variables are manipulated via the tf.Variable class. A tf.Variable represents a tensor whose value can be changed by running ops on it.

Example : tf.Variable("Welcome to tensorflow!!!")

将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列任意行数的矩阵。

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

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

不要把Python想象成一个通用的程序。你可以写一个Python程序,做所有那些在其他答案中通过变量解释的事情,但对于张量流中的计算图,为了将数据输入到图中,你需要将这些点定义为占位符。

变量

TensorFlow变量是表示程序操纵的共享持久状态的最佳方式。变量是通过tf操作的。变量类。内部是一个tf。变量存储一个持久张量。特定的操作允许你读取和修改这个张量的值。这些修改在多个tf中可见。会话,因此多个工作人员可以看到tf.Variable的相同值。变量在使用前必须初始化。

例子:

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

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

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

注意:维度的“None”表示“任何大小”。

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

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

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

  2. 变量:数据值将被改变,相应的函数,如cost_function..

  3. 占位符:训练/测试数据将被传递到图表中。

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

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

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

版本2中TF变量的等效命令。x是tf.Variable,如果你想从1迁移代码。X到2。X,等效命令为

tf.compat.v2.Variable

有关Tensorflow Version 2.0的更多信息,请参考Tensorflow页面

有关从版本1迁移的更多信息,请参考迁移向导。X到2。X。

对于TF V1:

  1. 常数是有初值的,在计算中不会改变;

  2. 变量有初值,在计算中可以改变;(对于参数来说很好)

  3. 占位符没有初始值,在计算中不会改变。(非常适合像预测实例这样的输入)

对于TF V2,同样,但他们试图隐藏占位符(图形模式不是首选)。

在TensorFlow中,变量只是另一个张量(比如tf。常量或tf.placeholder)。碰巧变量可以通过计算来修改。特遣部队。占位符用于将在运行时提供给计算的外部输入(例如训练数据)。特遣部队。变量用于作为计算的一部分并将被计算修改的输入(例如神经网络的权重)。