[PYTHON] [TensorFlow] Je souhaite maîtriser l'indexation pour Ragged Tensor

introduction

Ragged Tensor qui représente des données de longueur variable introduites dans TensorFlow 2.1 ou version ultérieure, mais si vous essayez d'écrire avec de la colle Tensor ordinaire, il existe plusieurs J'en suis accro. Cette fois, c'est l'indexation. Essayez de récupérer la valeur de `` RaggedTensor '' en spécifiant un index spécifique. Au fur et à mesure que vous vous y habituerez, vous pourrez effectuer des opérations compliquées ...

Environnement de vérification

Exemple d'indexation

Supposons que x '' soit créé en tant que RaggedTensor '' pour être indexé comme suit.

x = tf.RaggedTensor.from_row_lengths(tf.range(15), tf.range(1, 6))
print(x)
# <tf.RaggedTensor [[0], [1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13, 14]]>
Index des colonnes 0 1 2 3 4
Ligne 0 0
La première ligne 1 2
2e ligne 3 4 5
3e ligne 6 7 8 9
4ème ligne 10 11 12 13 14

Trancher sur une ligne spécifique

La première opération consiste à récupérer une ligne, qui est identique à un Tensor '' normal. Vous pouvez le considérer comme numpy.ndarray ''. Si vous spécifiez une plage, ** inclut le premier index et n'inclut pas le dernier index. ** Si vous êtes un utilisateur Python, je pense qu'il n'y a pas de problème.

print(x[2])
# tf.Tensor([3 4 5], shape=(3,), dtype=int32)
print(x[1:4])
# <tf.RaggedTensor [[1, 2], [3, 4, 5], [6, 7, 8, 9]]>

Cependant, contrairement à `` numpy.ndarray '', il semble que le découpage qui spécifie des lignes discrètes ne peut pas être utilisé.

#Cela peut être fait pour ndarray
print(x.numpy()[[1, 3]])                                                                                                                    
# [array([1, 2], dtype=int32) array([6, 7, 8, 9], dtype=int32)]

# Tensor/Non disponible pour Ragged Tensor
print(x[[1, 3]])
# InvalidArgumentError: slice index 3 of dimension 0 out of bounds. [Op:StridedSlice] name: strided_slice/

Veuillez plutôt aller ici.

# Tensor/Indexation sophistiquée avec Tensor Ragged
print(tf.gather(x, [1, 3], axis=0))
# <tf.RaggedTensor [[1, 2], [6, 7, 8, 9]]>

Tranchage avec index de colonne fixe

Voici un exemple de découpage avec un index de colonne fixe. Contrairement au `` Tensor '' ordinaire, cela dépend de la ligne, qu'il y ait ou non un élément de l'index, donc simplement

print(x[:, 2])
# ValueError: Cannot index into an inner ragged dimension.

Il n'est pas possible de faire comme. Si vous spécifiez la plage

print(x[:, 2:3])
# <tf.RaggedTensor [[], [], [5], [8], [12]]>

Cela fonctionne comme. C'est `` [] '' pour la ligne où l'index spécifié n'existe pas.

Index des colonnes 0 1 2 3 4
Ligne 0 0
La première ligne 1 2
2e ligne 3 4 5
3e ligne 6 7 8 9
4ème ligne 10 11 12 13 14

Découpage avec un index de colonne différent pour chaque ligne

Si vous avez un Tensor '' qui répertorie les index bidimensionnels que vous souhaitez collecter, vous pouvez utiliser tf.gather_nd () ''.

ind = tf.constant([[0, 0], [1, 1], [2, 0], [4, 3]])
#X(0, 0), (1, 1), (2, 0), (4, 3)Je veux collecter des éléments
print(tf.gather_nd(x, ind))
# tf.Tensor([ 0  2  3 13], shape=(4,), dtype=int32)
Index des colonnes 0 1 2 3 4
Ligne 0 0
La première ligne 1 2
2e ligne 3 4 5
3e ligne 6 7 8 9
4ème ligne 10 11 12 13 14

D'un autre côté, je récupère un élément pour chaque ligne, mais je pense qu'il y a des moments où vous voulez récupérer des colonnes différentes.

col = tf.constant([0, 0, 2, 1, 2])
#X(0, 0), (1, 0), (2, 2), (3, 1), (4, 2)Je veux collecter des éléments
#Ajoutez des numéros de ligne à l'index, puis utilisez la même méthode qu'auparavant
ind = tf.transpose(tf.stack([tf.range(tf.shape(col)[0]), col]))
print(tf.gather_nd(x, ind))
# tf.Tensor([ 0  1  5  7 12], shape=(5,), dtype=int32)
Index des colonnes 0 1 2 3 4
Ligne 0 0
La première ligne 1 2
2e ligne 3 4 5
3e ligne 6 7 8 9
4ème ligne 10 11 12 13 14

Mais j'ai l'impression qu'il va être tard, alors j'ai pensé à une manière plus intelligente.

print(tf.gather(x.values, x.row_starts() + col))
# tf.Tensor([ 0  1  5  7 12], shape=(5,), dtype=int32)

C'est acceptable. La valeur réelle de x '' est contenue dans Tensor '' (pas RaggedTensor '') qui relie chaque ligne (une dimension en moins) et peut être obtenue en accédant à x.values ''. Je vais. Il contient également des informations sur l'index de début de chaque ligne (x.row_starts () '') pour représenter la forme de x ''. Par conséquent, vous pouvez ajouter le décalage spécifié à cet index et découper par rapport à x.values.

%timeit tf.gather_nd(x, tf.transpose(tf.stack([tf.range(tf.shape(col)[0]), col])))
# 739 µs ± 75.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit tf.gather(x.values, x.row_starts() + col)                                                                                           
# 124 µs ± 6.47 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Celui-ci est plus rapide (^_^)

Si vous voulez maîtriser l'opération ici, il est bon de voir le document officiel.

Si l'index de colonne est dans un Tensor Ragged

Appliquez ci-dessus "la substance de la valeur est dans le" Tensor "unidimensionnel".

col = tf.ragged.constant([[0], [], [0, 2], [1, 3], [2]])
#X(0, 0), (2, 0), (2, 2), (3, 1), (3, 3), (4, 2)Je veux collecter des éléments

#Obtenez l'index de début de chaque ligne de x
row_starts = tf.cast(x.row_starts(), "int32")
#Obtenez le numéro de ligne auquel appartient chaque composant de col, convertissez-le en index de départ à x et ajoutez le décalage
ind_flat = tf.gather(row_starts, col.value_rowids()) + col.values
ret = tf.gather(x.values, ind_flat)
print(ret)
# tf.Tensor([ 0  3  5  7  9 12], shape=(6,), dtype=int32)
Index des colonnes 0 1 2 3 4
Ligne 0 0
La première ligne 1 2
2e ligne 3 4 5
3e ligne 6 7 8 9
4ème ligne 10 11 12 13 14

Si vous souhaitez enregistrer les informations de la ligne d'origine

Le résultat ci-dessus est un Tensor '' normal avec les valeurs répertoriées et les informations de la ligne d'origine sont perdues, mais que faire si vous souhaitez enregistrer les informations de la ligne? Vous pouvez créer un RaggedTensor '' en donnant les informations Tensor '' sur l'index de début de ligne. La longueur de chaque ligne doit correspondre à col '', vous pouvez donc apporter cet index de départ à partir de `` col.value_rowids () ''.

print(tf.RaggedTensor.from_value_rowids(ret, col.value_rowids()))
# <tf.RaggedTensor [[0], [], [3, 5], [7, 9], [12]]>

Lorsque la cible Ragged Tensor est de 3 dimensions ou plus

Même si les données de 2 dimensions ou plus sont classées par ordre chronologique (3 dimensions ou plus pour `` RaggedTensor '', y compris les dimensions du lot), la méthode existante peut être utilisée telle quelle.

x = tf.RaggedTensor.from_row_lengths(tf.reshape(tf.range(30), (15, 2)), tf.range(1, 6))
print(x)
# <tf.RaggedTensor [[[0, 1]], [[2, 3], [4, 5]], [[6, 7], [8, 9], [10, 11]], [[12, 13], [14, 15], [16, 17], [18, 19]], [[20, 21], [22, 23], [24, 25], [26, 27], [28, 29]]]>

La structure de ce `` x '' peut être interprétée comme suit.

Index des colonnes 0 1 2 3 4
Ligne 0 [0, 1]
La première ligne [2, 3] [4, 5]
2e ligne [6, 7] [8, 9] [10, 11]
3e ligne [12, 13] [14, 15] [16, 17] [18, 19]
4ème ligne [20, 21] [22, 23] [24, 25] [26, 27] [28, 29]

Le reste est exactement le même qu'avant. Cependant, veuillez noter que le `` Tensor '' renvoyé est bidimensionnel.

ind = tf.constant([[0, 0], [1, 1], [2, 0], [4, 3]])
#X(0, 0), (1, 1), (2, 0), (4, 3)Je veux collecter des éléments
print(tf.gather_nd(x, ind))
# tf.Tensor(
# [[ 0  1]
#  [ 4  5]
#  [ 6  7]
#  [26 27]], shape=(4, 2), dtype=int32)
col = tf.constant([0, 0, 2, 1, 2])
#X(0, 0), (1, 0), (2, 2), (3, 1), (4, 2)Je veux collecter des éléments
print(tf.gather(x.values, x.row_starts() + col))
# tf.Tensor(
# [[ 0  1]
#  [ 2  3]
#  [10 11]
#  [14 15]
#  [24 25]], shape=(5, 2), dtype=int32)
col = tf.ragged.constant([[0], [], [0, 2], [1, 3], [2]])
#X(0, 0), (2, 0), (2, 2), (3, 1), (3, 3), (4, 2)Je veux collecter des éléments

#Obtenez l'index de début de chaque ligne de x
row_starts = tf.cast(x.row_starts(), "int32")
#Obtenez le numéro de ligne auquel appartient chaque composant de col, convertissez-le en index de départ à x et ajoutez le décalage
ind_flat = tf.gather(row_starts, col.value_rowids()) + col.values
ret = tf.gather(x.values, ind_flat)
print(ret)
# tf.Tensor(
# [[ 0  1]
#  [ 6  7]
#  [10 11]
#  [14 15]
#  [18 19]
#  [24 25]], shape=(6, 2), dtype=int32)

#Si vous souhaitez enregistrer les informations de la ligne d'origine
print(tf.RaggedTensor.from_value_rowids(ret, col.value_rowids()))
# <tf.RaggedTensor [[[0, 1]], [], [[6, 7], [10, 11]], [[14, 15], [18, 19]], [[24, 25]]]>

Recommended Posts

[TensorFlow] Je souhaite maîtriser l'indexation pour Ragged Tensor
[TensorFlow] Je souhaite traiter des fenêtres avec Ragged Tensor
J'ai essayé de porter le code écrit pour TensorFlow sur Theano
Je veux déplacer le sélénium pour le moment [pour mac]
Je veux créer un Dockerfile pour le moment.
[Pour ceux qui veulent utiliser TPU] J'ai essayé d'utiliser l'API de détection d'objets Tensorflow 2
Pour le moment, je veux convertir n'importe quel fichier avec ffmpeg !!
Je veux épingler Spyder à la barre des tâches
Je veux sortir froidement sur la console
J'ai essayé tensorflow pour la première fois
Je veux gérer la rime part1
Je veux gérer la rime part3
Je veux afficher la barre de progression
Je veux gérer la rime part2
Je veux gérer la rime part5
Je veux gérer la rime part4
Le moyen le plus rapide pour les débutants de maîtriser Python
Je veux gérer la rime part7 (BOW)
[Je veux classer les images à l'aide de Tensorflow] (2) Classifions les images
Je souhaite personnaliser l'apparence de zabbix
Je souhaite utiliser la fonction d'activation Mish
Je veux afficher la progression en Python!
Je veux ajouter du silence pendant 1 seconde au début d'un fichier wav
Je veux voir le nom de fichier de DataLoader
Je veux utiliser self avec Backpropagation (tf.custom_gradient) (tensorflow)
Je veux grep le résultat de l'exécution de strace
Je veux faire défiler la table de décalage Django, mais ...
J'ai essayé le tutoriel MNIST de tensorflow pour les débutants.
Je veux hériter de l'arrière avec la classe de données python
Je veux bien comprendre les bases de Bokeh
Je veux écrire en Python! (3) Utiliser des simulacres
Je veux gérer la rime part6 (organiser une fois)
Je veux automatiser ssh en utilisant la commande expect!
Je souhaite publier le produit au moindre coût
Je veux utiliser le jeu de données R avec python
Je veux gérer la rime part8 (fini une fois)
Je souhaite augmenter la sécurité de la connexion SSH
Je veux juste trouver l'intervalle de confiance à 95% de la différence de ratio de population en Python
Je souhaite créer une base de données de déjeuners [EP1] Django pour la première fois
Je souhaite créer une base de données de déjeuner [EP1-4] Django pour la première fois
Je veux utiliser la dernière version de gcc même si je n'ai pas les privilèges sudo! !!
Je veux initialiser si la valeur est vide (python)
Je souhaite enregistrer les photos envoyées par LINE vers S3
Je veux échanger des cadeaux même pour moi! [Christmas Hackason]
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
Je veux automatiser ssh en utilisant la commande expect! partie 2
maya Python Je veux réparer à nouveau l'animation cuite.
Je veux voir quelque chose de beau, alors j'ai essayé de visualiser la fonction utilisée pour comparer la fonction d'optimisation.
[NetworkX] Je souhaite rechercher des nœuds avec des attributs spécifiques
[Pour les débutants] Je souhaite expliquer le nombre d’apprentissage d’une manière facile à comprendre.
Je souhaite utiliser uniquement le traitement de normalisation SudachiPy
Je veux obtenir des informations sur le fonctionnement de Yahoo Route
Je veux changer le drapeau japonais en drapeau des Palaos avec Numpy
Je veux résoudre SUDOKU
Pour ceux qui souhaitent démarrer l'apprentissage automatique avec TensorFlow2
Je souhaite calculer le temps d'arrêt autorisé à partir du taux de fonctionnement
[Python] Je souhaite utiliser l'option -h avec argparse
Je veux absorber la différence entre l'instruction for sur la matrice Python + numpy et l'instruction Julia for
Je veux déterminer l'authenticité d'un élément du tableau numpy
Je ne savais pas comment utiliser l'instruction [python] for
Je souhaite utiliser l'environnement de bureau d'Ubuntu sur Android pour le moment (version Termux)