在TensorFlow中,有一类特殊的节点,它既可以看成常量也可以看成变量,它就是placeholder。placeholder其实是一个占位符,它提前在图中占位,但是不需要给它初始化值。
之所以说placeholder既可以看成常量也可以看成变量, 是因为在将数据填入到占位符后,其值在图中就不能再做修改(即不能通过assign等函数修改值);但是在图之外又可以不断传入不同的值。在图运行的时候,可以动态设置placeholder的值。
举个例子,在训练的时候,需要向图中不断传入不同的数据(如图片),这个时候可以选择用placeholder提前占位,然后在训练时不断将placeholder中的数据替换。当然, TensorFlow中有其他更高效的数据读取方法,这里仅仅是举例。
在TensorFlow1中,tf.placeholder函数的原型如下:
tf.placeholder(
dtype,
shape=None,
name=None
)
各个参数的含义介绍如下:
dtype: 占位符的数据类型。
shape: 占位符的Shape,即各个维度的长度。
name: 占位符的名称。
写个例子,假设我们需要实现一个矩阵乘法,其中一个矩阵需要在一个矩阵列表中依次读取,并与另一个矩阵做相乘的计算,代码如下:
import tensorflow as tf
tf1 = tf.compat.v1
B = [[1, 1], [1, 1], [1, 1]]
Graph = tf1.Graph()
with Graph.as_default():
A_tf = tf1.placeholder(dtype=tf.float32, shape=[2, 3], name='A')
B_tf = tf1.constant(B, dtype=tf.float32, shape=[3, 2], name='B')
C_tf = tf1.matmul(A_tf, B_tf)
with tf1.Session(graph=Graph) as sess:
A1 = [[1, 2, 3], [1, 2, 3]]
A2 = [[4, 5, 6], [4, 5, 6]]
A_list = [A1, A2]
for A in A_list:
C = sess.run(C_tf, feed_dict={A_tf: A})
print('\n', C)
在第14行中,执行矩阵乘法运算,并将占位符A_tf的值通过feed_dict参数传入。feed_dict参数是一个字典对象,所有的占位符都可以通过这个参数传入。执行以上代码后,输出结果如下:
[[6. 6.]
[6. 6.]]
[[15. 15.]
[15. 15.]]
注意: 当执行的路径中包含占位符时,那么所有被包含的占位符必须要传入具体值,即通过feed_dict把所有路径中包含的占位符的值传入。