web-dev-qa-db-fra.com

Indexation du tenseur avec tenseur booléen

Dans numpy, avec deux tableaux de même forme, x et y, il est possible de créer des tranches comme celle-ci y[x > 1]. Comment obtenez-vous le même résultat en tensorflow? y[tf.greater(x, 1)] ne fonctionne pas et tf.slice ne supporte rien de ce genre non plus. Existe-t-il un moyen d'indexer avec un tenseur booléen actuellement ou est-ce actuellement non pris en charge?

18
pythonic metaphor

Essayer:

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)

Voir tf.boolean_mask

EDIT: une autre (meilleure?) façon de le faire:

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]
15
Mr_and_Mrs_D

Je ne dirais pas que ce n'est pas complètement implémenté. Comment ça pour un double négatif? 

Tensorflow prend en charge de nombreux découpages en tranches et en dés, bien que la syntaxe soit un peu moins jolie. Par exemple, si vous voulez créer un nouveau tableau qui vaut y quand x>1 mais égal à 0 sinon, vous pouvez certainement le faire. Check out opérateurs de comparaison p. Ex.

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

Si, par contre, vous voulez créer un nouveau tableau qui ne contient que les types où x>1 vous pouvez le faire en combinant where avec la fonction gather. Les détails pour gather peuvent être trouvés à

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

PS. Bien sûr, x>1 n'est pas différentiable en ce qui concerne x... tf peut être formidable, mais cela ne fonctionne pas comme par magie :). 

6
Jackson Loper

Ceci n’est pas encore implémenté, voici le numéro de GitHub qui suit l’avancement - https://github.com/tensorflow/tensorflow/issues/206

3
Yaroslav Bulatov

tf.boolean_mask fait le travail, mais sur certaines plates-formes telles que Raspberry Pi ou OSX, l'opération n'est pas prise en charge dans les distributions de roulettes Tensorflow (Cochez this tf.boolean_mask non pris en charge sur OSX . Une alternative consiste donc à utiliser where et gather comme @ Jackson Loper a suggéré, par exemple:

x = tf.Variable([1, 2, 0, 4])
ix = tf.where(x > 1)
y = tf.gather(x, ix)

with tf.Session() as sess:
 sess.run(tf.global_variables_initializer())
 print(sess.run(y))
0
pateheo

Je cherchais une capacité similaire pour réduire un tenseur de TensorFlow.js selon un critère défini, mais TensorFlow.js ne dispose pas de la fonction boolean_mask. Après avoir tiré beaucoup de cheveux et grincé des dents, voici ce qui est résumé, ce qui résume essentiellement le nombre total de vrais critères, puis il suffit de sélectionner les valeurs topk pour créer le tenseur.

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

Et pour créer un tenseur de sous-ensemble de valeurs inférieur ou égal à 1, il suffit d'utiliser tf.neg sur le tenseur puisqu'il n'y a pas de fonction de bottomk, puis après avoir obtenu le tenseur via topk, en appliquant à nouveau tf.neg pour restaurer les valeurs d'origine.

0
Jon Trent