我将特定顺序的项目排入TensorFlow FIFOQueue
,并期望能够以相同的顺序将它们出列,但这不是我观察到的行为。
运行以下独立代码演示了方法和行为。这已经在TensorFlow 1.1上运行在Python 2.7上(但可能在Python 3中有效)。
from __future__ import division, print_function, unicode_literals
import math
import numpy
import tensorflow as tf
from tensorflow.python.training import queue_runner
from tensorflow.python.ops import control_flow_ops
row_count, column_count = 7, 5
batch_size, step_size = 3, 2
# Create some random data
data = numpy.arange(row_count * column_count).reshape(
(row_count, column_count))
print(data)
batch_count = int(math.ceil(row_count / batch_size))
step_count = int(math.ceil(column_count / step_size))
print(batch_count, step_count)
slices = tf.train.slice_input_producer([data], num_epochs=1, shuffle=False)
batch = tf.train.batch(slices, batch_size, allow_smaller_final_batch=True)
queue = tf.FIFOQueue(32, dtypes=[batch.dtype])
enqueue_ops = []
dependency = None
for step_index in range(step_count):
step = tf.strided_slice(
batch, [0, step_index * step_size],
[tf.shape(batch)[0], (step_index + 1) * step_size])
if dependency is None:
dependency = step
else:
step = control_flow_ops.with_dependencies([dependency], step)
enqueue_ops.append(queue.enqueue(step))
queue_runner.add_queue_runner(queue_runner.QueueRunner(
queue=queue, enqueue_ops=[tf.group(*enqueue_ops)]))
step = queue.dequeue()
supervisor = tf.train.Supervisor()
with supervisor.managed_session() as session:
for batch_index in range(batch_count):
for step_index in range(step_count):
print("Batch %d, step %d" % (batch_index, step_index))
print(session.run(step))
预期输出
Batch 0, step 0
[[ 0 1]
[ 5 6]
[10 11]]
Batch 0, step 1
[[ 2 3]
[ 7 8]
[12 13]]
Batch 0, step 2
[[ 4]
[ 9]
[14]]
Batch 1, step 0
[[15 16]
[20 21]
[25 26]]
Batch 1, step 1
[[17 18]
[22 23]
[27 28]]
Batch 1, step 2
[[19]
[24]
[29]]
Batch 2, step 0
[[30 31]]
Batch 2, step 1
[[32 33]]
Batch 2, step 2
[[34]]
实际输出是
Batch 0, step 0
[[ 0 1]
[ 5 6]
[10 11]]
Batch 0, step 1
[[ 4]
[ 9]
[14]]
Batch 0, step 2
[[ 2 3]
[ 7 8]
[12 13]]
Batch 1, step 0
[[15 16]
[20 21]
[25 26]]
Batch 1, step 1
[[19]
[24]
[29]]
Batch 1, step 2
[[17 18]
[22 23]
[27 28]]
Batch 2, step 0
[[30 31]]
Batch 2, step 1
[[32 33]]
Batch 2, step 2
[[34]]
请注意,批次0和1中的步骤顺序不正确。我一直无法确定步骤的顺序。似乎批次总是按顺序排列,但每批中的步骤以“随机”顺序出现:它看起来是确定性的,但不是FIFO。
我尝试过使用和不使用上面代码中使用的显式依赖声明。我已经尝试将队列容量设置为1.我尝试设置enqueue_ops=enqueue_ops
而不是使用tf.group
,但这些更改都没有帮助,最后一个导致非常奇怪的输出。
也许tf.group
忽略了依赖关系?
答案 0 :(得分:0)
tensorflow.python.ops.control_flow_ops.with_dependencies
似乎没有按照我的想法工作,或者我使用不正确。如果我转而使用tf.control_dependencies
,我会得到我需要的行为:
from __future__ import division, print_function, unicode_literals
import math
import numpy
import tensorflow as tf
from tensorflow.python.training import queue_runner
row_count, column_count = 7, 5
batch_size, step_size = 3, 2
# Create some random data
data = numpy.arange(row_count * column_count).reshape(
(row_count, column_count))
print(data)
batch_count = int(math.ceil(row_count / batch_size))
step_count = int(math.ceil(column_count / step_size))
print(batch_count, step_count)
slices = tf.train.slice_input_producer([data], num_epochs=1, shuffle=False)
batch = tf.train.batch(slices, batch_size, allow_smaller_final_batch=True)
queue = tf.FIFOQueue(32, dtypes=[batch.dtype])
enqueue_ops = []
dependency = None
for step_index in range(step_count):
step = tf.strided_slice(
batch, [0, step_index * step_size],
[tf.shape(batch)[0], (step_index + 1) * step_size])
if dependency is None:
dependency = queue.enqueue(step)
else:
with tf.control_dependencies([dependency]):
step = queue.enqueue(step)
dependency = step
enqueue_ops.append(step)
queue_runner.add_queue_runner(queue_runner.QueueRunner(
queue=queue, enqueue_ops=[tf.group(*enqueue_ops)]))
step = queue.dequeue()
supervisor = tf.train.Supervisor()
with supervisor.managed_session() as session:
for batch_index in range(batch_count):
for step_index in range(step_count):
print("Batch %d, step %d" % (batch_index, step_index))
print(session.run(step))
这个答案是由answer to another SO question推动的。