TensorFlow——计算图管理


整体说明

  • 在 TensorFlow 1.x 里,placeholder函数用于创建占位符张量
  • 定义计算图时 :定义计算图时指定输入数据的形状类型
  • 在会话中执行图时 :在运行计算图时需要为这些占位符张量提供具体数值
    • 注意:这个数值不能是TensorFlow的Tensor类型,必须是numpy或者Python原生类型
    • 注意:当实际运行会话(Session)并传入数据时,如果 placeholder 的类型与实际输入数据的类型不一致,TensorFlow 会抛出错误

placeholder函数的定义

  • 函数定义:

    1
    tf.placeholder(dtype, shape=None, name=None)
    • dtype:必须指定,代表占位符张量的数据类型,像tf.float32tf.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
    41
    import 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
    33
    import 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}')
  • 同时使用Datasetplaceholder的示例:

    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
    41
    import 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)