Python 如何使用TensorFlow阅读器和队列同时读取两个文件?
我的训练集包含两种文件:文件名为“1.png”的训练图像和名称为“1.label.txt”的标签文件 我在以下教程中发现了Queue和Reader的一些用法: 但是,因为我的训练集包含两种文件,一种对应一种。我如何使用上面的队列和类似读卡器的代码Python 如何使用TensorFlow阅读器和队列同时读取两个文件?,python,tensorflow,Python,Tensorflow,我的训练集包含两种文件:文件名为“1.png”的训练图像和名称为“1.label.txt”的标签文件 我在以下教程中发现了Queue和Reader的一些用法: 但是,因为我的训练集包含两种文件,一种对应一种。我如何使用上面的队列和类似读卡器的代码 编辑 我正在考虑使用一个包含基本名称的队列来馈送到另两个队列,分别是image和label。代码如下: 但运行此代码将导致错误: TypeError:的Fetch参数的类型无效,必须是字符串或张量。(无法将FIFOQueue转换为张量或运算。)
编辑 我正在考虑使用一个包含基本名称的队列来馈送到另两个队列,分别是image和label。代码如下: 但运行此代码将导致错误: TypeError:的Fetch参数的类型无效,必须是字符串或张量。(无法将FIFOQueue转换为张量或运算。) 错误点指向这一行:
coord.join(enqueue_threads)
我想我一定误解了TensorFlow队列的工作原理。我已经找到了解决问题的方法。我想在这里发布答案,而不是删除我的问题,希望这将有助于新加入TensorFlow的人
答案包括两部分:
第1部分:如何使用TensorFlow的队列逐对读取文件
解决方案很简单:
dequeue
进行一些预处理李>
shuffle\u batch
base_names = ['file1', 'file2']
base_tensor = tf.convert_to_tensor(base_names)
image_name_queue = tf.train.string_input_producer(
tensor + '.png',
shuffle=False # Note: must set shuffle to False
)
label_queue = tf.train.string_input_producer(
tensor + '.lable.txt',
shuffle=False # Note: must set shuffle to False
)
# use reader to read file
image_reader = tf.WholeFileReader()
image_key, image_raw = image_reader.read(image_name_queue)
image = tf.image.decode_png(image_raw)
label_reader = tf.WholeFileReader()
label_key, label_raw = label_reader.read(label_queue)
label = tf.image.decode_raw(label_raw)
# preprocess image
processed_image = tf.image.per_image_whitening(image)
batch = tf.train.shuffle_batch([processed_image, label], 10, 100, 100)
# print batch
queue_threads = queue_runner.start_queue_runners()
print(sess.run(batch))
第2部分:队列、QueueRunner、协调器和帮助器函数
队列实际上是一个队列(似乎毫无意义)。队列有两种方法:enqueue
和dequeue
。enqueue
的输入是Tensor
(当然,您可以将普通数据排队,但它将在内部转换为Tensor
)。dequeue
的返回值是一个Tensor
。因此,您可以按如下方式创建队列管道:
q1 = data_flow_ops.FIFOQueue(32, tf.int)
q2 = data_flow_ops.FIFOQueue(32, tf.int)
enq1 = q1.enqueue([1,2,3,4,5])
v1 = q1.dequeue()
enq2 = q2.enqueue(v1)
在TensorFlow中使用队列的好处是异步加载数据,这将提高性能并节省内存。上面的代码不可运行,因为没有线程运行这些操作。QueueRunner旨在描述如何将数据并行排队。因此,初始化QueueRunner的参数是一个enqueue
操作(enqueue的输出)
设置完所有的QueueRunner
s后,必须启动所有线程。一种方法是在创建它们时启动它们:
enqueue_threads = qr.create_threads(sess, coord=coord, start=True)
或者,您可以在完成所有设置工作后启动所有线程:
# add queue runner
queue_runner.add_queue_runner(queue_runner.QueueRunner(q, [enq]))
# start all queue runners
queue_threads = queue_runner.start_queue_runners()
当所有线程启动时,您必须决定何时退出。协调员是来做这件事的<代码>协调器类似于所有运行线程之间的共享标志。如果其中一个线程完成或出错,它将调用coord.request\u stop()
,那么在调用coord.should\u stop()
时,所有线程都将得到True
。因此,使用协调器的模式是:
coord = tf.train.Coordinator()
for step in range(1000000):
if coord.should_stop():
break
print(sess.run(print_op))
coord.request_stop()
coord.join(enqueue_threads)
使用两个队列的方法可能会产生一些负面后果。因为您的一个队列将保存图像数据(大)和另一个文本数据(小),所以其中一个队列有可能落后于另一个队列
相反,我建议你去看看。然后构造一个由数据和标签组成的tfrecord文件。之后,只需使用一个队列即可同时获取数据和标签。在定义
image\u name\u queue
和label\u queue
的部分,如果对两者使用相同的种子,则可以将shuffle
设置为true
,例如,将seed=123
添加到两个tf.train.string\u input\u producer
@MGoksu是的,你完全正确。我最近才发现那件事。感谢您的提醒。感谢您指出tf.train.string\u input\u producer的shuffle
参数。解决了我所经历的不确定行为:)
# add queue runner
queue_runner.add_queue_runner(queue_runner.QueueRunner(q, [enq]))
# start all queue runners
queue_threads = queue_runner.start_queue_runners()
coord = tf.train.Coordinator()
for step in range(1000000):
if coord.should_stop():
break
print(sess.run(print_op))
coord.request_stop()
coord.join(enqueue_threads)