simonszu
simonszu

Reputation: 376

Update slices of variables in Tensorflow

I have the following code snippet, written in Lua with torch, which is a custom edge detection algorithm:

 xGrad1[{{},{},{},{1,width-1}}] = input:narrow(4,2,width-1) - input:narrow(4,1,width-1)
 yGrad1[{{},{},{1,height-1},{}}] = input:narrow(3,2,height-1) - input:narrow(3,1,height-1)
 xGrad2[{{},{},{},{2,width}}] = input:narrow(4,2,width-1) - input:narrow(4,1,width-1)
 yGrad2[{{},{},{2,height},{}}] = input:narrow(3,2,height-1) - input:narrow(3,1,height-1)

 local xGrad = (torch.abs(self.xGrad1) + torch.abs(self.xGrad2))/2
 local yGrad = (torch.abs(self.yGrad1) + torch.abs(self.yGrad2))/2
 output = torch.sum(xGrad,2)+torch.sum(yGrad,2)

As you can see, the last two dimensions of the xGrad and yGrad tensors, which represent width and height of an image, are only partially updated, e.g. in xGrad2 only the columns 2 to width-1.

Now i want to achieve the same result with Tensorflow and Python. I am not sure if my general approach is right, but i have initialized all 4 Grad-tensors as a variable and pre-filled them with zeros. Now i am struggling with these partial assigns. I tried it with Variable.assign but have no luck.

Currently, this is my code:

input = tf.image.decode_png(tf.read_file(f), 3)
input = tf.cast(input, tf.float32)

height = tf.shape(input)[0]
width = tf.shape(input)[1]

xGrad1 = tf.Variable(tf.zeros(tf.shape(input)), validate_shape=False)
yGrad1 = tf.Variable(tf.zeros(tf.shape(input)), validate_shape=False)
xGrad2 = tf.Variable(tf.zeros(tf.shape(input)), validate_shape=False)
yGrad2 = tf.Variable(tf.zeros(tf.shape(input)), validate_shape=False)

xGrad1[:, :width-2].assign(input[:,1:width-2] - input[:,:width-2])
yGrad1[:height-2].assign(input[1:height-2] - input[:height-2])
xGrad2[:, 1:width-1].assign(input[:,1:width-2] - input[:,:width-2])
yGrad2 [1, height-1].assign(input[1:height-2] - input[:height-2])

xGrad = (tf.abs(xGrad1) + tf.abs(xGrad2)) / 2
yGrad = (tf.abs(yGrad1) + tf.abs(yGrad2)) / 2

output = tf.reduce_sum(xGrad,axis=2) + tf.reduce_sum(yGrad,axis=2)

After translating the list indices from Lua to python, i get decent results when directly outputting the calculations which are the arguments of the 4 assign-commands, but only a black image when outputting the contents of xGrad1 and so on.

I assume a problem with incompatible shapes, but i have switched validate_shapes to False, since i do not know the shape of input at session creation time, since the input image is loaded after the session starts. If someone has an idea for this as well, feel free to answer me, but for now i am only asking how to only partially assign a variable tensor.

Upvotes: 1

Views: 1321

Answers (1)

Nipun Wijerathne
Nipun Wijerathne

Reputation: 1829

If you want to do a sliced assignment you have to follow something like this,

with tf.control_dependencies([xGrad1[:, :width-2].assign(input[:,1:width-2] - input[:,:width-2]), yGrad1[:height-2].assign(input[1:height-2] - input[:height-2]),xGrad2[:, 1:width-1].assign(input[:,1:width-2] - input[:,:width-2]),yGrad2 [1, height-1].assign(input[1:height-2] - input[:height-2])]): # should give the list of slice assignment here
 xGrad = (tf.abs(xGrad1) + tf.abs(xGrad2)) / 2
 yGrad = (tf.abs(yGrad1) + tf.abs(yGrad2)) / 2

output = tf.reduce_sum(xGrad,axis=2) + tf.reduce_sum(yGrad,axis=2)

sess = tf.Session()
with sess.as_default():
    sess.run(tf.global_variables_initializer())
    output= output.eval()

Here is a nice explanation of sliced assignment in Tensorflow, https://stackoverflow.com/a/43139565/6531137

Hope this helps.

Upvotes: 1

Related Questions