tf.train.string_input_producer 在循环中的行为 [英] tf.train.string_input_producer behavior in a loop

查看:36
本文介绍了tf.train.string_input_producer 在循环中的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下片段摘自 TensorFlow 0.12 API 文档

The following snippet has been taken from the TensorFlow 0.12 API documentation

def input_pipeline(filenames, batch_size, num_epochs=None):
  filename_queue = tf.train.string_input_producer(
      filenames, num_epochs=num_epochs, shuffle=True)
  example, label = read_my_file_format(filename_queue)
  # min_after_dequeue defines how big a buffer we will randomly sample
  #   from -- bigger means better shuffling but slower start up and more
  #   memory used.
  # capacity must be larger than min_after_dequeue and the amount larger
  #   determines the maximum we will prefetch.  Recommendation:
  #   min_after_dequeue + (num_threads + a small safety margin) * batch_size
  min_after_dequeue = 10000
  capacity = min_after_dequeue + 3 * batch_size
  example_batch, label_batch = tf.train.shuffle_batch(
      [example, label], batch_size=batch_size, capacity=capacity,
      min_after_dequeue=min_after_dequeue)
  return example_batch, label_batch

我的问题对于普通 TensorFlow 用户来说可能非常基础,但我绝对是初学者.问题如下:

The question I have might be very basic for a regular TensorFlow user, but I am an absolute beginner. The question is the following :

  • tf.train.string_input_producer 创建一个队列来保存文件名.由于 input_pipeline() 在训练期间被一遍又一遍地调用,如何确保每次都使用相同的队列?我想,这很重要,因为如果对 input_pipeline() 的不同调用导致创建新队列,似乎没有办法确保每次都选择不同的图像和纪元计数器并且可以适当地维护洗牌.
  • tf.train.string_input_producer creates a queue for holding the filenames. As the input_pipeline() is called over and over again during training, how will it be ensured that everytime the same queue is used ? I guess, it is important since, if different calls to input_pipeline() result in a creation of a new queue, there does not seem to be a way to ensure that different images are picked everytime and epoch counter and shuffling can be properly maintained.

推荐答案

input_pipeline 函数仅创建负责生成批量数据的图(通常更大)的一部分.如果您要两次调用 input_pipeline - 无论出于何种原因 - 您确实会创建两个不同的队列.

The input_pipeline function only creates the part of a (usually larger) graph that is responsible for producing batches of data. If you were to call input_pipeline twice - for whatever reason - you would be creating two different queues indeed.

一般来说,tf.train.string_input_producer 函数实际上在当前活动图中创建了一个队列node(或操作)(它是默认图形,除非您指定不同的内容).read_my_file_format 然后从该队列中读取并依次生成单个示例"张量,而 tf.train.shuffle_batch 然后将这些张量分成长度为 batch_size 的束每个.

In general, the function tf.train.string_input_producer actually creates a queue node (or operation) in the currently active graph (which is the default graph unless you specify something different). read_my_file_format then reads from that queue and sequentially produces single "example" tensors, while tf.train.shuffle_batch then batches these into bundles of length batch_size each.

然而,tf.train.shuffle_batch 的输出,这里是从 input_pipeline 函数返回的两个张量,只有当它在会话下评估.如果您多次评估这些张量,它们将包含不同的值 - 通过 read_my_file_format 从输入队列中列出的文件中获取.

However, the output of tf.train.shuffle_batch, two Tensors here that are returned from the input_pipeline function, only really takes on a (new) value when it is evaluated under a session. If you evaluate these tensors multiple times, they will contain different values - taken, through read_my_file_format, from files listed in the input queue.

这样想:

X_batch, Y_batch = input_pipeline(..., batch_size=100)

with tf.Session() as sess:
   sess.run(tf.global_variable_initializer())   
   tf.train.start_queue_runners()

   # get the first 100 examples and labels
   X1, Y1 = sess.run((X_batch, Y_batch))

   # get the next 100 examples and labels
   X2, Y2 = sess.run((X_batch, Y_batch))

   # etc.

让它运行的样板代码有点复杂,例如因为队列需要在图中实际启动和停止,因为它们在运行时会抛出 tf.errors.OutOfRangeError 等.更完整的示例可能如下所示:

The boilerplate code to get it running is a bit more complex, e.g. because queues need to actually be started and stopped in the graph, because they will throw a tf.errors.OutOfRangeError when they run dry, etc. A more complete example could look like this:

with tf.Graph().as_default() as graph:
   X_batch, Y_batch = input_pipeline(..., batch_size=100)

   prediction = inference(X_batch)
   optimizer, loss = optimize(prediction, Y_batch)

coord = tf.train.Coordinator()
with tf.Session(graph=graph) as sess:
   init = tf.group(tf.local_variable_initializer(),
                   tf.global_variable_initializer())
   sess.run(init)

   # start the queue runners
   threads = tf.train.start_queue_runners(coord=coord)

   try:
       while not coord.should_stop():

           # now you're really indirectly querying the
           # queue; each iteration will see a new batch of
           # at most 100 values.
           _, loss = sess.run((optimizer, loss))

           # you might also want to do something with
           # the network's output - again, this would
           # use a fresh batch of inputs
           some_predicted_values = sess.run(prediction)

   except tf.errors.OutOfRangeError:
       print('Training stopped, input queue is empty.')
   finally:
       coord.request_stop()

   # stop the queue(s)
   coord.request_stop()
   coord.join(threads)

要更深入地了解,您可能需要查看阅读数据文档.

For a deeper understanding, you might want to look at the Reading data documentation.

这篇关于tf.train.string_input_producer 在循环中的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆