Matthew Guo Matthew Guo - 1 month ago 13
Python Question

TensorFlow stuck into endless loop using tf.while_loop()

Steps to reproduce



I am using TensorFlow to implement a network that needs to use
tf.while_loop()


import tensorflow as tf
import numpy as np
class model(object):
def __init__(self):
self.argmax_ep_gate_array = [ tf.placeholder(tf.int32, [None]) for _ in range(10)]
argmax_ep_gate_array_concat = tf.concat(0, self.argmax_ep_gate_array)
story_len = tf.constant(7)
starter = tf.constant(0)
z = []
def body(hops):
hops = tf.add(hops,1)
z.append(hops)
return hops
def condition(hops):
return tf.logical_and(tf.less(tf.gather(argmax_ep_gate_array_concat, hops),story_len),tf.less(hops,tf.constant(20)))

self.gate_index = tf.while_loop(condition,body,[starter])
self.z=tf.concat(0,z)

def step(self, sess):
feed={}
for i in range(10):
feed[self.argmax_ep_gate_array[i].name]=[i]
print (sess.run([self.gate_index,self.z],feed))
with tf.Session() as sess:
while_loop = model()
sess.run(tf.initialize_all_variables())
while_loop.step(sess)


What have you tried?



I find that If I want to sess.run() any variable in the body() that is not returned, tensorflow would stuck into endless loop.
The above example is trivial, but it reveals something. In the real case, I am using
tf.while_loop()
running a RNN which includes y= wx+b something like that, but the
w
and
b
are not returned after while loop. In the forward network, it works fine. However, if I run the back propagation, the program would stuck into endless loop. I suppose the code above reproducing my issue, because back propagation do need to modify
w
and
b
. Or is there any way to handle this issue?

Answer

TL;DR: You cannot store tensors that were created in the loop body for later use, because that breaks some assumptions about how the loop is structured.

In general, the condition() and body() functions must not have side effects. Indeed, it is unlikely that your program has the intended behavior: TensorFlow will execute the body() function once, to build the necessary graph structure, so z will only contain one element after running model.__init__().

Instead, you must construct z incrementally in the loop body, using tf.concat() and producing the value as a loop variable:

starter = tf.constant(0)
z_initial = tf.constant([], dtype=tf.int32)

def body(hops, z_prev):
    hops = tf.add(hops, 1)
    z_next = tf.concat(0, [z_prev, tf.expand_dims(hops, 0)])
    return hops, z_next
def condition(hops, z):
    return tf.logical_and(tf.less(tf.gather(
        argmax_ep_gate_array_concat, hops), story_len), tf.less(hops, tf.constant(20)))

self.gate_index, self.z = tf.while_loop(condition,body,[starter, z_initial])