Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tensorflow indexing with boolean tensor

Tags:

In numpy, with two arrays of the same shape, x and y, it is possible to do slices like this y[x > 1]. How do you achieve the same result in tensorflow? y[tf.greater(x, 1)] doesn't work and tf.slice doesn't support anything like this either. Is there a way to index with a boolean tensor right now or is that currently unsupported?

like image 974
pythonic metaphor Avatar asked Nov 17 '15 23:11

pythonic metaphor


4 Answers

Try:

ones = tf.ones_like(x) # create a tensor all ones
mask = tf.greater(x, ones) # boolean tensor, mask[i] = True iff x[i] > 1
slice_y_greater_than_one = tf.boolean_mask(y, mask)

See tf.boolean_mask

EDIT: another (better ?) way to do it:

import tensorflow as tf

x = tf.constant([1, 2, 0, 4])
y = tf.Variable([1, 2, 0, 4])
mask = x > 1
slice_y_greater_than_one = tf.boolean_mask(y, mask)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print (sess.run(slice_y_greater_than_one)) # [2 4]
like image 109
Mr_and_Mrs_D Avatar answered Oct 03 '22 15:10

Mr_and_Mrs_D


I would not say it is completely not implemented. How's that for a double negative?

Tensorflow actually supports quite a lot of slicing and dicing, although the syntax may be slightly less pretty. For example, if you want to create a new array which is equal to y when x>1 but equal to 0 otherwise, you can definitely do that. Check out comparison operators e.g.

masked = tf.greater(x,1)
zeros = tf.zeros_like(x)
new_tensor = tf.where(masked, y, zeros)

If, on the other hand, you want to make a new array which contains only the guys where x>1 you can do that by combining where with the gather function. Details for gather can be found at

https://www.tensorflow.org/versions/master/api_docs/python/array_ops/slicing_and_joining

PS. Of course, x>1 is not differentiable with respect to x... tf may be great, but it doesn't work magic :).

like image 20
Jackson Loper Avatar answered Oct 04 '22 15:10

Jackson Loper


This is not implemented at this moment, here's GitHub issue tracking the progress -- https://github.com/tensorflow/tensorflow/issues/206

like image 3
Yaroslav Bulatov Avatar answered Oct 01 '22 15:10

Yaroslav Bulatov


Was looking for similar capability to reduce a TensorFlow.js tensor by a defined criteria, but TensorFlow.js does not have the boolean_mask function. After much hair pulling and teeth gnashing, cooked up the following, which essentially sums up the total number of true criteria, and then simply selects the topk values to create the subset tensor.

const a = tf.tensor1d([1, 2, 0, 4]);
const b = a.greater(1).sum().get();
const {values, indices} = tf.topk(a, b);
values.print();   # 4,2
indices.print();  # 3,1

And to create a subset tensor of values less than or equal to 1, it's a matter of using tf.neg on the tensor as there is no bottomk function, and then after obtaining the subset tensor via topk, applying tf.neg again to restore the original values.

like image 2
Trentium Avatar answered Oct 04 '22 15:10

Trentium