5

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)
1
  • Please pass your solution as an answer not an edit to the question, you can find your solution in revisions 3, just copy and past it into an answer Commented Jul 6, 2017 at 12:21

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that gets rid of the error. However, if I move the cost_matrix Variable declaration outside the loop, and remove it from the loop variables, cost remains 1.0 while I expect it to be 100.0
Apparently I didn't realize the operation must be used by the output variable in order to be run. I assume this has something to do with the way TF interprets and optimizes the code. I used a hacky solution to overcome this but I assume there's a better way to do this (see edit in the question). Will ask a new question about this.
Update: Triggering the operation to be run can be done using tf.control_dependencies() (working solution in question updated).
1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.