TensorFlow:当批次完成训练时,tf.train.batch 会自动加载下一批吗?

Posted

技术标签:

【中文标题】TensorFlow:当批次完成训练时,tf.train.batch 会自动加载下一批吗?【英文标题】:TensorFlow: does tf.train.batch automatically load the next batch when the batch has finished training? 【发布时间】:2017-05-31 03:27:22 【问题描述】:

例如,在我创建了操作后,通过操作输入批处理数据并运行操作,tf.train.batch 是否会自动将另一批数据输入会话?

我问这个是因为 tf.train.batch 具有allow_smaller_final_batch 的属性,这使得最终批次可以加载为小于指定批次大小的大小。这是否意味着即使没有循环,下一批也可以自动喂食?从教程代码中我很困惑。当我加载一个批次时,我实际上得到了一个形状为 [batch_size, height, width, num_channels] 的批次大小,但是documentation 说它Creates batches of tensors in tensors. 另外,当我阅读tf-slim walkthrough tutorial 中的教程代码时,其中有一个名为 load_batch 的函数,只返回 3 个张量:images, images_raw, labels。文档中解释的“批次”数据在哪里?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

我对@9​​87654321@ 中的代码和上述帖子中的bodokaiser 答案进行了修改。请注意,这是来自https://github.com/tensorflow/models/tree/master/research/slim 的评估脚本,eval_image_classifier.py。对 eval_image_classifier.py 代码最重要的修改是将 num_epochs=1 添加到 DatasetDataProvider 行。这样,所有图像都将被访问一次以进行推理。

provider = slim.dataset_data_provider.DatasetDataProvider(
    dataset,
    shuffle=False,
    common_queue_capacity=2 * FLAGS.batch_size,
    common_queue_min=FLAGS.batch_size, num_epochs=1)
[image, label] = provider.get(['image', 'label'])
images, labels = tf.train.batch(
    [image, label],
    batch_size=FLAGS.batch_size,
    num_threads=FLAGS.num_preprocessing_threads,
    capacity=1 * FLAGS.batch_size)
with tf.Session() as sess:
     sess.run([tf.local_variables_initializer(),
               tf.global_variables_initializer(),])
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    try:
        while not coord.should_stop():
            np_image, np_label = sess.run([images, labels])
    except:
        coord.request_stop()
        coord.join(threads)

【讨论】:

【参考方案2】:

每次要加载下一批时,您都需要调用 sess.run 并将该批传递给它。请参阅下面的代码。

img = [0,1,2,3,4,5,6,7,8]
lbl = [0,1,2,3,4,5,6,7,8]
images = tf.convert_to_tensor(img)
labels = tf.convert_to_tensor(lbl)
input_queue = tf.train.slice_input_producer([images,labels])
sliced_img = input_queue[0]
sliced_lbl = input_queue[1]

img_batch, lbl_batch = tf.train.batch([sliced_img,sliced_lbl], batch_size=3)
with tf.Session() as sess:
    coord   = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(coord=coord)

    for i in range(0,3): #batch size
        image_batch,label_batch = sess.run([img_batch,lbl_batch ])
        print(image_batch, label_batch)

    coord.request_stop()
    coord.join(threads)

答案是这样的:

[4,1,8] [4,1,8]

[2,3,7] [2,3,7]

[2,6,8] [2,6,8]

【讨论】:

【参考方案3】:

... tf.train.batch 是否会自动将另一批数据输入会话?

没有。没有任何事情会自动发生。您必须再次调用 sess.run(...) 才能加载新批次。

这是否意味着即使没有循环,下一批也可以自动喂食?

没有。 tf.train.batch(..) 将始终加载 batch_size 张量。例如,如果您有 100 张图像和一个 batch_size=30,那么您将拥有 3*30 个批次,因为您可以在输入队列从头开始之前调用 sess.run(batch) 三次(或者如果 epoch=1 则停止)。这意味着您错过了训练中的100-3*30=10 样本。如果您不想错过它们,您可以使用tf.train.batch(..., allow_smaller_final_batch=True),所以现在您将拥有 3x 30-sample-batch 和 1x 10-sample-batch,然后输入队列将重新启动。

让我也用一个代码示例来详细说明:

queue = tf.train.string_input_producer(filenames,
        num_epochs=1) # only iterate through all samples in dataset once

reader = tf.TFRecordReader() # or any reader you need
_, example = reader.read(queue)

image, label = your_conversion_fn(example)

# batch will now load up to 100 image-label-pairs on sess.run(...)
# most tf ops are tuned to work on batches
# this is faster and also gives better result on e.g. gradient calculation
batch = tf.train.batch([image, label], batch_size=100)

with tf.Session() as sess:
    # "boilerplate" code
    sess.run([
        tf.local_variables_initializer(),
        tf.global_variables_initializer(),
    ])
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    try:
        # in most cases coord.should_stop() will return True
        # when there are no more samples to read
        # if num_epochs=0 then it will run for ever
        while not coord.should_stop():
            # will start reading, working data from input queue
            # and "fetch" the results of the computation graph
            # into raw_images and raw_labels
            raw_images, raw_labels = sess.run([images, labels])
    finally:
        coord.request_stop()
        coord.join(threads)

【讨论】:

感谢您的回答。我可以知道是否需要一个 for 循环来继续加载下一批?如果训练数据集中只有 100 个示例,您当前是否将 100 个示例加载到一批中?从我在 TF 中看到的大多数实现中,似乎有一个循环,但我的没有,所以我不确定这一点。此外,对于样板代码下面的代码,我使用了 tf-slim 的 slim.learning.train 代替,我认为除了采取的训练步数之外没有循环。 是的,如果训练数据集中只有 100 个示例,这将导致我的示例中只有一个批次。我不能推荐tf.contrib.slim,因为它只有很少的文档并且维护得不是很好。目前还不清楚他们是否会继续开发。 如果数据集中有超过 100 个示例,您建议我如何加载下一批?如果我通过 for 循环再次调用 tf.train.batch,它会调用相同的示例吗? 正如我在代码示例中通过while not coord.should_stop() 所做的那样。 batch_image, batch_label = tf.train.batch([image, label], batch_size=100) 和 tf.Session() 内部是否有意义,通过 raw_images, raw_labels = sess.run([batch_image, batch_label]) 将它们拉出来以充分利用批处理?在当前代码中,似乎我们仍然一次拉一个实例,因为我们没有在 batch 上运行,对吧?

以上是关于TensorFlow:当批次完成训练时,tf.train.batch 会自动加载下一批吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Tensorflow 中将数据拆分为批次进行分类

当训练数据是图像时,Keras model.fit() 中的“批次”是啥

Keras 中的自定义损失函数应该返回批次的单个损失值还是训练批次中每个样本的一系列损失?

如何使用 DataSet API 在 Tensorflow 中为 tf.train.SequenceExample 数据创建填充批次?

在执行第一个 epoch 后,Tensorflow 无法将批次附加在一起

TensorFlow——分布式的TensorFlow运行环境