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 ...
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 |
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]]>
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 |
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.
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 |
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]]>
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]]]>