0

I want to create a mask with iterating over the tensor. I have this code:

import tensorflow as tf

out = tf.Variable(tf.zeros_like(alp, dtype=tf.int32))

rows_tf = tf.constant (
[[1, 2, 5],
 [1, 2, 5],
 [1, 2, 5],
 [1, 4, 6],
 [1, 4, 6],
 [2, 3, 6],
 [2, 3, 6],
 [2, 4, 7]])

columns_tf = tf.constant(
[[1],
 [2],
 [3],
 [2],
 [3],
 [2],
 [3],
 [2]])

I want to iterate through rows_tf and accordingly columns_tf to create a mask over the out.

for example, it will mask the index at [1,1] [2,1] and [5,1] in the out tensor equals 1.

for the second row in rows_tf indexes at [1,2] [2,2] [5,2] in the out tensor will be set to 1 and so on for the total 8 rows

So far I have done this, though it does not run successfully:

body = lambda k, i: (tf.add(out[rows_tf[i][k]][columns_tf[i][i]], 1)) # find the corresponding element in out tensor and add 1 to it (0+1=1)
k = 0
n2, m2 = rows_tf.shape
for i in tf.range(0,n2): # loop through rows in rows_tf    
    cond = lambda k, _: tf.less(k, m2) #this check to go over the columns in rows_tf
    tf.while_loop(cond, body, (k, i))

it raises this error:

TypeError: Cannot iterate over a scalar tensor. 
in this while cond(*loop_vars):

I have gone through several links namely here to make sure Im following the instruction, but could not fix this one.

Thanks for the help

5
  • 1
    I did not look at your code - why tf.while_loop not working. but if you can use a tf.SparseTensor to represent your mask (can apply the mask with other sparse ops in module tf.sparse), you can do rows_tf = tf.reshape(rows_tf, shape=[-1, 1]) columns_tf = tf.reshape( tf.tile(columns_tf, multiples=[1, 3]), shape=[-1, 1]) mask_indices = tf.reshape( tf.concat([rows_tf, columns_tf], axis=-1), shape=[-1, 2]). The values of the mask would be all ones. Commented Jun 18, 2019 at 1:24
  • @greeness Thank you so much for following my question, I dont have access my computer now, I will check your idea tomorrow. Commented Jun 18, 2019 at 3:55
  • @greeness Again thanks for putting the time, it run successully, however it did not mask to out tensor, I used the below approach. again thank you:) Commented Jun 18, 2019 at 20:27
  • np. I +1'ed on jdehesa@'answer. What I got is scatter_idx in jdehesa's solution. :) Commented Jun 18, 2019 at 20:58
  • Yea, Now I checkd step by step got it the difference, thanks btw:). by any chance do you have any idea of this question? stackoverflow.com/questions/56636994/… I have to accomplish that but after tring different ways of slicing I did not get my desired output so I channged the approach that It will not be efficient Commented Jun 18, 2019 at 21:15

1 Answer 1

2

You can do that without a loop using tf.scatter_nd like this:

import tensorflow as tf

with tf.Graph().as_default(), tf.Session() as sess:
    out = tf.zeros([10, 4], dtype=tf.int32)
    rows_tf = tf.constant(
        [[1, 2, 5],
         [1, 2, 5],
         [1, 2, 5],
         [1, 4, 6],
         [1, 4, 6],
         [2, 3, 6],
         [2, 3, 6],
         [2, 4, 7]], dtype=tf.int32)
    columns_tf = tf.constant(
        [[1],
         [2],
         [3],
         [2],
         [3],
         [2],
         [3],
         [2]], dtype=tf.int32)
    # Broadcast columns
    columns_bc = tf.broadcast_to(columns_tf, tf.shape(rows_tf))
    # Scatter values to indices
    scatter_idx = tf.stack([rows_tf, columns_bc], axis=-1)
    mask = tf.scatter_nd(scatter_idx, tf.ones_like(rows_tf, dtype=tf.bool), tf.shape(out))
    print(sess.run(mask))

Output:

[[False False False False]
 [False  True  True  True]
 [False  True  True  True]
 [False False  True  True]
 [False False  True  True]
 [False  True  True  True]
 [False False  True  True]
 [False False  True False]
 [False False False False]
 [False False False False]]

Alternatively, you could also do this using boolean operations only:

import tensorflow as tf

with tf.Graph().as_default(), tf.Session() as sess:
    out = tf.zeros([10, 4], dtype=tf.int32)
    rows_tf = tf.constant(
        [[1, 2, 5],
         [1, 2, 5],
         [1, 2, 5],
         [1, 4, 6],
         [1, 4, 6],
         [2, 3, 6],
         [2, 3, 6],
         [2, 4, 7]], dtype=tf.int32)
    columns_tf = tf.constant(
        [[1],
         [2],
         [3],
         [2],
         [3],
         [2],
         [3],
         [2]], dtype=tf.int32)
    # Compare indices
    row_eq = tf.equal(tf.range(out.shape[0])[:, tf.newaxis],
                      rows_tf[..., np.newaxis, np.newaxis])
    col_eq = tf.equal(tf.range(out.shape[1])[tf.newaxis, :],
                      columns_tf[..., np.newaxis, np.newaxis])
    # Aggregate
    mask = tf.reduce_any(row_eq & col_eq, axis=[0, 1])
    print(sess.run(mask))
    # Same as before

However this would in principle take more memory.

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

3 Comments

Thank you so much@jdehesa, Actually the first one faced with error in the mask line. saying can not reshape it ... even if the shape of my tensor is exactly the same(I could run your code but when included in my code did not successfully run. however, the second one is working fine.
Hi again :) do you have any idea reagarding the question here: stackoverflow.com/questions/56730261/… , I really appreciate it if you could have a look :)
@sariii I have taken a look, but unfortunately I am not familiar with that kind of models, so I'm not sure I can help with it.

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.