Reputation: 1136
(Updated I forget to say the input is batched) Given a bool array, e.g. [[false, false, false, true, false, false, true, false, false], [false, true, false, false, false, false, true, false, false]]
, which "true" define the boundary of the separate sequence. I want to generate an adjacent matrix denoting the different group separated by the boundary. What is a good way to generate following "symmetric ladder" matrix using Tensorflow?
[[
[1 1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 1 0 0 0]
[0 0 0 0 1 1 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 1]
[0 0 0 0 0 0 0 1 1]
]
[
[1 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 1 1 1 1 1 0 0]
[0 0 1 1 1 1 1 0 0]
[0 0 1 1 1 1 1 0 0]
[0 0 1 1 1 1 1 0 0]
[0 0 1 1 1 1 1 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
]]
Update Jun 15 2018: Actually, I just have some progress on this problem, if I can convert the input senqence from [false, false, false, true, false, false, true, false, false] to [1, 1, 1, 0, 2, 2, 0, 3, 3], I can get some result using following Tensorflow code. But I am not sure is there a vector operation can convert [false, false, false, true, false, false, true, false, false] to [1, 1, 1, 0, 2, 2, 0, 3, 3]?
import tensorflow as tf
sess = tf.Session()
x = tf.constant([1, 1, 1, 0, 2, 2, 0, 3, 3], shape=(9, 1), dtype=tf.int32)
y = tf.squeeze(tf.cast(tf.equal(tf.expand_dims(x, 1), x), tf.int32))
print(sess.run(y))
[[1 1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0]
[0 0 0 1 0 0 1 0 0]
[0 0 0 0 1 1 0 0 0]
[0 0 0 0 1 1 0 0 0]
[0 0 0 1 0 0 1 0 0]
[0 0 0 0 0 0 0 1 1]
[0 0 0 0 0 0 0 1 1]]
Update finally: I inspired a lot from @Willem Van Onsem. For batched version can be solved by modifying a little from @Willem Van Onsem solution.
import tensorflow as tf
b = tf.constant([[False, False, False, True, False, False, True, False, False], [False, True, False, False, False, False, False, False, False]], shape=(2, 9, 1), dtype=tf.int32)
x = (1 + tf.cumsum(tf.cast(b, tf.int32), axis=1)) * (1-b)
x = tf.cast(tf.equal(x, tf.transpose(x, perm=[0,2,1])),tf.int32) - tf.transpose(b, perm=[0,2,1])*b
with tf.Session() as sess:
print(sess.run(x))
Upvotes: 2
Views: 142
Reputation: 476739
But I am not sure is there a vector operation can convert
[False, False, False, True, False, False, True, False, False]
to[1, 1, 1, 0, 2, 2, 0, 3, 3]
There is, consider the following example:
b = tf.constant([False, False, False, True, False, False, True, False, False], shape=(9,), dtype=tf.int32)
then we can use tf.cumsum(..)
to generate:
>>> print(sess.run(1+tf.cumsum(b)))
[1 1 1 2 2 2 3 3 3]
If we then multiply the values with the opposite of b
, we get:
>>> print(sess.run((1+tf.cumsum(b))*(1-b)))
[1 1 1 0 2 2 0 3 3]
So we can store this expression in a variable, for example x
:
x = (1+tf.cumsum(b))*(1-b)
I want to generate an adjacent matrix denoting the different group separated by the boundary. What is a good way to generate following "symmetric ladder" matrix using Tensorflow?
If we follow your approach, we only have to remove the points where both lists are 0
at the same time. We can do this with:
tf.cast(tf.equal(x, tf.transpose(x)),tf.int32) - tf.transpose(b)*b
So here we use your approach, where we basically broadcast x
, and the transpose of x
, and check for elementwise equality, and we subtract the element-wise multiplication of b
from, it. This then yields:
>>> print(sess.run(tf.cast(tf.equal(x, tf.transpose(x)),tf.int32) - tf.transpose(b)*b))
[[1 1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0]
[1 1 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 1 0 0 0]
[0 0 0 0 1 1 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 1]
[0 0 0 0 0 0 0 1 1]]
Upvotes: 1