2017-04-13 73 views
0

考虑这个简单的例子:Tensorflow出列内while_loop

l = [1,2,324,3,12,1,2,3] 
q = tf.train.input_producer(l, shuffle=False) 
x = q.dequeue() 

t = tf.TensorArray(dtype=tf.int32, size=5, dynamic_size=True, clear_after_read=True) 

_, t = tf.while_loop(cond=lambda i, a: tf.less(i, 5, name='less_op'), 
body=lambda i, a: [i+1, a.write(i, [x])], 
loop_vars=[0, t]) 

它输出[1 1 1 1 1],由于出队()被调用一次。请告诉我如何在每次迭代中触发出列操作。

谢谢!

干杯,克里斯

回答

1

问题的出现是因为tf.while_loop()体捕获张x作为不变的一个循环的 ,而你要出队要在循环内进行的副作用

的解决方案是将呼叫转移到q.dequeue()身体内部,如下所示:

import tensorflow as tf 

l = [1, 2, 324, 3, 12, 1, 2, 3] 
q = tf.train.input_producer(l, shuffle=False) 
t = tf.TensorArray(dtype=tf.int32, size=5, dynamic_size=True, clear_after_read=True) 

# N.B. set `parallel_iterations=1` to ensure that values are dequeued in a 
# deterministic FIFO order. 
_, t = tf.while_loop(cond=lambda i, a: tf.less(i, 5, name='less_op'), 
        body=lambda i, a: [i+1, a.write(i, [q.dequeue()])], 
        loop_vars=[0, t], 
        parallel_iterations=1) 

result = t.stack() 

sess = tf.Session() 
tf.train.start_queue_runners(sess) 
print(sess.run(result)) # ==> '[[1], [2], [324], [3], [12]]' 
print(sess.run(result)) # ==> '[[1], [2], [3], [1], [2]]' 
+0

确定,所以在情况下,我使用的读取器(任何种类的),I只需调用reader.read(Q )以同样的精神(而不是q.dequeue()))。但是在身体内使用批量数据呢?我可以考虑将批量加载到新队列中,但这有点脏。这件事还有其他解决方法吗?非常感谢你以前的回应(:! –

+1

是的,同样的原则适用于任何潜在的有状态的操作(如从阅读器读取或读取/写入变量)对于批量数据,您可以使用'reader.read_up_to( n)',并可选择将批量填充到全尺寸(因为如果'n'没有划分文件中确切的记录数,'read_up_to()'可以返回一个更小的批次)。 – mrry

+0

一如既往 - 非常丰富的答案。就像你知道我的下一个问题将会是什么一样(::最后一个难题是:如果我的.tfrecords文件中有_x_记录,并且我用_y_> _x_调用reader.read_up_to(y),我会去成为_x_记录,还是后续的文件将被取出?我认为前者是实际情况,但文档只是指出:_如果需要,将队列中的工作单元从队列中取出(例如,当Reader需要从新文件,因为它已经完成了前一个文件)。它可能会返回更少的t甚至在最后批次之前还有num_records__ –