mgray mgray - 3 months ago 39
Python Question

TensorFlow queue feed order

I'm wondering in what order TensorFlow queues feed data (specifically when you have a list of tensors that they're feeding from).

For example, in a queue like this:

fifo_q = tf.FIFOQueue(
capacity=10,
dtypes=[tf.string, tf.string]
shapes=[[], []])


If I enqueue these lists:

sess = tf.Session()

l = [str(i+1) for i in range(10)]
x = tf.constant(l)
y = tf.constant(l)

eq = fifo_q.enqueue_many([x, y])
dq1, dq2 = fifo_q.dequeue()
sess.run(eq)


I would expect
dq1
,
dq2
to be '1', '1' the on the first run, then '2', '2' and so on. But this isn't what's happening. Instead, when I run the following code, I get '1', '2' and then '3', '4', and so on until
dq2
reaches 10, and then the queue locks up.

for x in range(6):
print('dq1:', sess.run(dq1))
print('dq2:', sess.run(dq2))


Why does this happen instead of what I expect? I'm using this to match up training examples with labels, but some training examples and labels are skipped/off-set. Is a better solution just to interleave the file names in a single queue? Either way, I would like to understand this behavior.

Any help is appreciated.

Answer

TensorFlow queues allow you to enqueue and dequeue lists (more precisely fixed-length tuples) of tensors atomically, in a single operation. The tensors dq1 and dq2 are the outputs of the same dequeue operation, which in this case will remove a tuple of two tensors from the queue. Each invocation of sess.run(dq1) or sess.run(dq2) corresponds to a separate invocation of the dequeue operation, but when you invoke sess.run(dq1) TensorFlow discards the other tuple element, because you didn't explicitly request it in the call to sess.run().

The solution is to ensure that both outputs of the dequeue() operation are consumed in the same call to sess.run(). For example, the following change to your program should produce the result that you originally expected:

for x in range(6):
  dq1_val, dq2_val = sess.run([dq1, dq2])
  print('dq1:', dq1_val)
  print('dq2:', dq2_val)