So I want to get the index of the values that are not zero for every row in my matrix. I've tried with tf.where but the output is not like I expecteded.
My code now is:
b = tf.constant([[1,0,0,0,0],
[1,0,1,0,1]],dtype=tf.float32)
zero = tf.constant(0, dtype=tf.float32)
where = tf.not_equal(b, zero)
indices = tf.where(where)
And indices output is:
<tf.Tensor: id=136, shape=(4, 2), dtype=int64, numpy=
array([[0, 0],
[1, 0],
[1, 2],
[1, 4]])>
But I would like the output to be:
[[0],
[0,2,4]]
Where I have a list with the indexes per row.
Thanks.
That cannot be a proper tensor, since dimensions are not uniform. If you are okay with using a ragged tensor you can do:
import tensorflow as tf
with tf.Graph().as_default(), tf.Session() as sess:
b = tf.constant([[1, 0, 0, 0, 0],
[1, 0, 1, 0, 1]],dtype=tf.float32)
num_rows = tf.shape(b)[0]
zero = tf.constant(0, dtype=tf.float32)
where = tf.not_equal(b, zero)
indices = tf.where(where)
s = tf.ragged.segment_ids_to_row_splits(indices[:, 0], num_rows)
row_start = s[:-1]
elem_per_row = s[1:] - row_start
idx = tf.expand_dims(row_start, 1) + tf.ragged.range(elem_per_row)
result = tf.gather(indices[:, 1], idx)
print(sess.run(result))
# <tf.RaggedTensorValue [[0], [0, 2, 4]]>
EDIT: If you don't want to or cannot use ragged tensors, here is an alternative. You can produce a tensor padded with "invalid" values. You can either have for example -1 in those invalid values, or just have a 1D tensor that tells you how many valid values you have on each row:
import tensorflow as tf
with tf.Graph().as_default(), tf.Session() as sess:
b = tf.constant([[1, 0, 0, 0, 0],
[1, 0, 1, 0, 1]],dtype=tf.float32)
num_rows = tf.shape(b)[0]
zero = tf.constant(0, dtype=tf.float32)
where = tf.not_equal(b, zero)
indices = tf.where(where)
num_indices = tf.shape(indices)[0]
elem_per_row = tf.bincount(tf.cast(indices[:, 0], tf.int32), minlength=num_rows)
row_start = tf.concat([[0], tf.cumsum(elem_per_row[:-1])], axis=0)
max_elem_per_row = tf.reduce_max(elem_per_row)
r = tf.range(max_elem_per_row)
idx = tf.expand_dims(row_start, 1) + r
idx = tf.minimum(idx, num_indices - 1)
result = tf.gather(indices[:, 1], idx)
# Optional: replace invalid elements with -1
result = tf.where(tf.expand_dims(elem_per_row, 1) > r, result, -tf.ones_like(result))
print(sess.run(result))
# [[ 0 -1 -1]
# [ 0 2 4]]
print(sess.run(elem_per_row))
# [1 3]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With