Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TensorFlow while_loop converts variable to constant?

I'm trying to update a two dimensional tensor in a nested while_loop(). When passing the variable to the second loop however, I cannot updated it using tf.assign() as it throws this error:

ValueError: Sliced assignment is only supported for variables

Somehow it works fine if I create the variable outside the while_loop and use it only in the first loop.

How can I modify my 2D tf variable in the second while loop?
(I'm using python 2.7 and TensorFlow 1.2)

My code:

import tensorflow as tf
import numpy as np

tf.reset_default_graph()

BATCH_SIZE = 10
LENGTH_MAX_OUTPUT = 31

it_batch_nr = tf.constant(0)
it_row_nr = tf.Variable(0, dtype=tf.int32)
it_col_nr = tf.constant(0)
cost = tf.constant(0)

it_batch_end = lambda it_batch_nr, cost: tf.less(it_batch_nr, BATCH_SIZE)
it_row_end = lambda it_row_nr, cost_matrix: tf.less(it_row_nr, LENGTH_MAX_OUTPUT+1)

def iterate_batch(it_batch_nr, cost):
    cost_matrix = tf.Variable(np.ones((LENGTH_MAX_OUTPUT+1, LENGTH_MAX_OUTPUT+1)), dtype=tf.float32)
    it_rows, cost_matrix = tf.while_loop(it_row_end, iterate_row, [it_row_nr, cost_matrix])
    cost = cost_matrix[0,0] # IS 1.0, SHOULD BE 100.0
    return tf.add(it_batch_nr,1), cost

def iterate_row(it_row_nr, cost_matrix):
    # THIS THROWS AN ERROR:
    cost_matrix[0,0].assign(100.0)
    return tf.add(it_row_nr,1), cost_matrix

it_batch = tf.while_loop(it_batch_end, iterate_batch, [it_batch_nr, cost])

sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
out = sess.run(it_batch)
print(out)
like image 809
Deruijter Avatar asked Oct 18 '22 09:10

Deruijter


2 Answers

tf.Variable objects cannot be used as loop variables in a while loop, as loop variables are implemented differently.

So either create your variable outside the loop and update it yourself with tf.assign in each iteration or manually keep track of the updates as you do with loop variables (by returning their updated values from the loop lambdas, and in your case using the value from the inner loop as the new value for the outer loop).

like image 57
Alexandre Passos Avatar answered Oct 21 '22 05:10

Alexandre Passos


Got this to work, with @AlexandrePassos help, by placing the Variable outside the while_loop. However, I also had to force the execution of the commands using tf.control_dependencies() (as the operations are not directly used on the loop variable). The loop now looks like this:

cost_matrix = tf.Variable(np.ones((LENGTH_MAX_OUTPUT+1, LENGTH_MAX_OUTPUT+1)), dtype=tf.float32)

def iterate_batch(it_batch_nr, cost):
    it_rows = tf.while_loop(it_row_end, iterate_row, [it_row_nr])
    with tf.control_dependencies([it_rows]):
        cost = cost_matrix[0,0] 
        return tf.add(it_batch_nr,1), cost

def iterate_row(it_row_nr):
    a = tf.assign(cost_matrix[0,0], 100.0)
    with tf.control_dependencies([a]):
        return tf.add(it_row_nr,1)
like image 1
Deruijter Avatar answered Oct 21 '22 06:10

Deruijter