整体说明
- 在 TensorFlow 1.x 里,
placeholder函数用于创建占位符张量 - 定义计算图时 :定义计算图时指定输入数据的形状和类型
- 在会话中执行图时 :在运行计算图时需要为这些占位符张量提供具体数值
- 注意:这个数值不能是TensorFlow的Tensor类型,必须是numpy或者Python原生类型
- 注意:当实际运行会话(Session)并传入数据时,如果 placeholder 的类型与实际输入数据的类型不一致,TensorFlow 会抛出错误
placeholder函数的定义
函数定义:
1
tf.placeholder(dtype, shape=None, name=None)
dtype:必须指定,代表占位符张量的数据类型,像tf.float32、tf.int32等shape:可选参数,代表占位符张量的形状- 常见的设置为
shape=(None, 2),表示第一维为batch_size,维度可变 - 注:若设为
shape=None,就表示可以接受任意形状的输入
- 常见的设置为
name:可选参数,为占位符张量赋予名称,方便调试和可视化
placeholder函数的示例
- 示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import tensorflow as tf
# 创建占位符
x = tf.placeholder(tf.float32, shape=[None, 2], name='x')
y = tf.placeholder(tf.float32, shape=[None, 1], name='y')
# 定义计算图
w = tf.Variable(tf.random_normal([2, 1]), name='w')
b = tf.Variable(tf.zeros([1]), name='b')
pred = tf.matmul(x, w) + b
loss = tf.reduce_mean(tf.square(pred - y))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(loss)
# 初始化变量
init = tf.global_variables_initializer()
# 模拟数据
import numpy as np
x_data = np.array([[1, 2], [3, 4], [5, 6]])
y_data = np.array([[3], [7], [11]])
# 运行计算图
with tf.Session() as sess:
sess.run(init)
for i in range(100):
_, loss_val = sess.run([train_op, loss], feed_dict={x: x_data, y: y_data})
if (i + 1) % 10 == 0:
print(f'Step {i + 1}, Loss: {loss_val}')
# Step 10, Loss: 0.23915673792362213
# Step 20, Loss: 0.2156977653503418
# Step 30, Loss: 0.19454030692577362
# Step 40, Loss: 0.17545770108699799
# Step 50, Loss: 0.15824727714061737
# Step 60, Loss: 0.1427248865365982
# Step 70, Loss: 0.1287250965833664
# Step 80, Loss: 0.1160985603928566
# Step 90, Loss: 0.10471046715974808
# Step 100, Loss: 0.09443938732147217
placeholder使用过程中需要注意的问题
- 数据类型匹配 :在使用
feed_dict为占位符提供数据时,要保证提供的数据类型和占位符定义的数据类型一致,不然会引发类型错误 - 形状匹配 :提供的数据形状必须和占位符定义的形状相匹配。要是占位符形状中有
None,那就表示该维度可以接受任意长度的输入 - 必须提供值 :在运行计算图时,所有依赖占位符的操作都得在
feed_dict里为占位符提供具体的值,否则会抛出异常- 计算目标不依赖的的不输入
- 性能问题 :频繁使用
feed_dict会带来一定的性能开销,尤其是在处理大规模数据时。可以考虑使用tf.data.Dataset来提升性能
附录:使用tf.data.Dataset提升性能
tf.data.Dataset提升性能的示例代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import tensorflow as tf
import numpy as np
x_data = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.float32)
y_data = np.array([[3], [7], [11]], dtype=np.float32)
dataset = tf.data.Dataset.from_tensor_slices((x_data, y_data)) # 创建 tf.data.Dataset
dataset = dataset.repeat().batch(3) # 对数据集进行重复和批量处理
iterator = dataset.make_one_shot_iterator()# 创建迭代器
next_x, next_y = iterator.get_next() # 获取下一个批次的数据
# 定义计算图
w = tf.Variable(tf.random_normal([2, 1]), name='w')
b = tf.Variable(tf.zeros([1]), name='b')
pred = tf.matmul(next_x, w) + b
# 定义损失函数
loss = tf.reduce_mean(tf.square(pred - next_y))
# 定义优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(loss)
# 初始化变量
init = tf.global_variables_initializer()
# 运行计算图
with tf.Session() as sess:
sess.run(init)
for i in range(100):
_, loss_val = sess.run([train_op, loss]) # 由于不使用placeholder,故而无需使用feed_back
if (i + 1) % 10 == 0:
print(f'Step {i + 1}, Loss: {loss_val}')同时使用
Dataset和placeholder的示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import tensorflow as tf
import numpy as np
train_x = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.float32)
train_y = np.array([[3], [7], [11]], dtype=np.float32)
# 创建训练数据集
train_dataset = tf.data.Dataset.from_tensor_slices((train_x, train_y))
train_dataset = train_dataset.shuffle(buffer_size=len(train_x)).batch(3).repeat()
# 创建迭代器
train_iterator = train_dataset.make_one_shot_iterator()
next_train_x, next_train_y = train_iterator.get_next()
# 通过placeholder定义模型
x = tf.placeholder(tf.float32, shape=[None, 2])
w = tf.Variable(tf.random_normal([2, 1]), name='w')
b = tf.Variable(tf.zeros([1]), name='b')
pred = tf.matmul(x, w) + b
# 通过Dataset输出,重新定义训练损失函数(包含模型结构,即如何训练模型变量 w)
train_pred = tf.matmul(next_train_x, w) + b
train_loss = tf.reduce_mean(tf.square(train_pred - next_train_y))
# 定义优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(train_loss)
# 初始化变量
init = tf.global_variables_initializer()
# 训练模型
with tf.Session() as sess:
sess.run(init)
for i in range(100):
sess.run(train_op) # 由于train_op不依赖placeholder,无需使用feed_back
# 使用 feed_dict 进行推理
test_x = np.array([[7, 8]], dtype=np.float32)
prediction = sess.run(pred, feed_dict={x: test_x}) # pred依赖placeholder,故而需要使用feed_back
print("推理结果:", prediction)