Voir sur TensorFlow.org | Exécuter dans Google Colab | Voir la source sur GitHub | Télécharger le cahier |
Lorsque vous travaillez sur des applications ML telles que la détection d'objets et le NLP, il est parfois nécessaire de travailler avec des sous-sections (tranches) de tenseurs. Par exemple, si l'architecture de votre modèle inclut le routage, une couche peut contrôler quel exemple de formation est acheminé vers la couche suivante. Dans ce cas, vous pouvez utiliser des opérations de découpage de tenseurs pour diviser les tenseurs et les remettre ensemble dans le bon ordre.
Dans les applications NLP, vous pouvez utiliser le découpage du tenseur pour effectuer un masquage de mots pendant l'entraînement. Par exemple, vous pouvez générer des données d'apprentissage à partir d'une liste de phrases en choisissant un index de mots à masquer dans chaque phrase, en retirant le mot comme étiquette, puis en remplaçant le mot choisi par un jeton de masque.
Dans ce guide, vous apprendrez à utiliser les API TensorFlow pour :
- Extraire des tranches d'un tenseur
- Insérer des données à des indices spécifiques dans un tenseur
Ce guide suppose une familiarité avec l'indexation du tenseur. Lisez les sections d'indexation des guides Tensor et TensorFlow NumPy avant de commencer avec ce guide.
Installer
import tensorflow as tf
import numpy as np
Extraire des tranches de tenseur
Effectuez un découpage de tenseur de type NumPy à l'aide tf.slice
.
t1 = tf.constant([0, 1, 2, 3, 4, 5, 6, 7])
print(tf.slice(t1,
begin=[1],
size=[3]))
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
Alternativement, vous pouvez utiliser une syntaxe plus Pythonique. Notez que les tranches de tenseur sont régulièrement espacées sur une plage start-stop.
print(t1[1:4])
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
print(t1[-3:])
tf.Tensor([5 6 7], shape=(3,), dtype=int32)
Pour les tenseurs bidimensionnels, vous pouvez utiliser quelque chose comme :
t2 = tf.constant([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
print(t2[:-1, 1:3])
tf.Tensor( [[ 1 2] [ 6 7] [11 12]], shape=(3, 2), dtype=int32)
Vous pouvez également utiliser tf.slice
sur des tenseurs de dimension supérieure.
t3 = tf.constant([[[1, 3, 5, 7],
[9, 11, 13, 15]],
[[17, 19, 21, 23],
[25, 27, 29, 31]]
])
print(tf.slice(t3,
begin=[1, 1, 0],
size=[1, 1, 2]))
tf.Tensor([[[25 27]]], shape=(1, 1, 2), dtype=int32)
Vous pouvez également utiliser tf.strided_slice
pour extraire des tranches de tenseurs en 'marquant' sur les dimensions du tenseur.
Utilisez tf.gather
pour extraire des indices spécifiques d'un seul axe d'un tenseur.
print(tf.gather(t1,
indices=[0, 3, 6]))
# This is similar to doing
t1[::3]
tf.Tensor([0 3 6], shape=(3,), dtype=int32) <tf.Tensor: shape=(3,), dtype=int32, numpy=array([0, 3, 6], dtype=int32)>
tf.gather
ne nécessite pas que les indices soient espacés de manière régulière.
alphabet = tf.constant(list('abcdefghijklmnopqrstuvwxyz'))
print(tf.gather(alphabet,
indices=[2, 0, 19, 18]))
tf.Tensor([b'c' b'a' b't' b's'], shape=(4,), dtype=string)
Pour extraire des tranches de plusieurs axes d'un tenseur, utilisez tf.gather_nd
. Ceci est utile lorsque vous souhaitez rassembler les éléments d'une matrice plutôt que ses lignes ou ses colonnes uniquement.
t4 = tf.constant([[0, 5],
[1, 6],
[2, 7],
[3, 8],
[4, 9]])
print(tf.gather_nd(t4,
indices=[[2], [3], [0]]))
tf.Tensor( [[2 7] [3 8] [0 5]], shape=(3, 2), dtype=int32)
t5 = np.reshape(np.arange(18), [2, 3, 3])
print(tf.gather_nd(t5,
indices=[[0, 0, 0], [1, 2, 1]]))
tf.Tensor([ 0 16], shape=(2,), dtype=int64)
# Return a list of two matrices
print(tf.gather_nd(t5,
indices=[[[0, 0], [0, 2]], [[1, 0], [1, 2]]]))
tf.Tensor( [[[ 0 1 2] [ 6 7 8]] [[ 9 10 11] [15 16 17]]], shape=(2, 2, 3), dtype=int64)
# Return one matrix
print(tf.gather_nd(t5,
indices=[[0, 0], [0, 2], [1, 0], [1, 2]]))
tf.Tensor( [[ 0 1 2] [ 6 7 8] [ 9 10 11] [15 16 17]], shape=(4, 3), dtype=int64)
Insérer des données dans des tenseurs
Utilisez tf.scatter_nd
pour insérer des données à des tranches/indices spécifiques d'un tenseur. Notez que le tenseur dans lequel vous insérez des valeurs est initialisé à zéro.
t6 = tf.constant([10])
indices = tf.constant([[1], [3], [5], [7], [9]])
data = tf.constant([2, 4, 6, 8, 10])
print(tf.scatter_nd(indices=indices,
updates=data,
shape=t6))
tf.Tensor([ 0 2 0 4 0 6 0 8 0 10], shape=(10,), dtype=int32)
Les méthodes telles que tf.scatter_nd
qui nécessitent des tenseurs initialisés à zéro sont similaires aux initialiseurs de tenseurs clairsemés. Vous pouvez utiliser tf.gather_nd
et tf.scatter_nd
pour imiter le comportement des opérations de tenseur clairsemées.
Prenons un exemple où vous construisez un tenseur creux en utilisant ces deux méthodes en conjonction.
# Gather values from one tensor by specifying indices
new_indices = tf.constant([[0, 2], [2, 1], [3, 3]])
t7 = tf.gather_nd(t2, indices=new_indices)
# Add these values into a new tensor
t8 = tf.scatter_nd(indices=new_indices, updates=t7, shape=tf.constant([4, 5]))
print(t8)
tf.Tensor( [[ 0 0 2 0 0] [ 0 0 0 0 0] [ 0 11 0 0 0] [ 0 0 0 18 0]], shape=(4, 5), dtype=int32)
Ceci est similaire à :
t9 = tf.SparseTensor(indices=[[0, 2], [2, 1], [3, 3]],
values=[2, 11, 18],
dense_shape=[4, 5])
print(t9)
SparseTensor(indices=tf.Tensor( [[0 2] [2 1] [3 3]], shape=(3, 2), dtype=int64), values=tf.Tensor([ 2 11 18], shape=(3,), dtype=int32), dense_shape=tf.Tensor([4 5], shape=(2,), dtype=int64))
# Convert the sparse tensor into a dense tensor
t10 = tf.sparse.to_dense(t9)
print(t10)
tf.Tensor( [[ 0 0 2 0 0] [ 0 0 0 0 0] [ 0 11 0 0 0] [ 0 0 0 18 0]], shape=(4, 5), dtype=int32)
Pour insérer des données dans un tenseur avec des valeurs préexistantes, utilisez tf.tensor_scatter_nd_add
.
t11 = tf.constant([[2, 7, 0],
[9, 0, 1],
[0, 3, 8]])
# Convert the tensor into a magic square by inserting numbers at appropriate indices
t12 = tf.tensor_scatter_nd_add(t11,
indices=[[0, 2], [1, 1], [2, 0]],
updates=[6, 5, 4])
print(t12)
tf.Tensor( [[2 7 6] [9 5 1] [4 3 8]], shape=(3, 3), dtype=int32)
De même, utilisez tf.tensor_scatter_nd_sub
pour soustraire des valeurs d'un tenseur avec des valeurs préexistantes.
# Convert the tensor into an identity matrix
t13 = tf.tensor_scatter_nd_sub(t11,
indices=[[0, 0], [0, 1], [1, 0], [1, 1], [1, 2], [2, 1], [2, 2]],
updates=[1, 7, 9, -1, 1, 3, 7])
print(t13)
tf.Tensor( [[1 0 0] [0 1 0] [0 0 1]], shape=(3, 3), dtype=int32)
Utilisez tf.tensor_scatter_nd_min
pour copier les valeurs minimales par élément d'un tenseur à un autre.
t14 = tf.constant([[-2, -7, 0],
[-9, 0, 1],
[0, -3, -8]])
t15 = tf.tensor_scatter_nd_min(t14,
indices=[[0, 2], [1, 1], [2, 0]],
updates=[-6, -5, -4])
print(t15)
tf.Tensor( [[-2 -7 -6] [-9 -5 1] [-4 -3 -8]], shape=(3, 3), dtype=int32)
De même, utilisez tf.tensor_scatter_nd_max
pour copier les valeurs maximales par élément d'un tenseur à un autre.
t16 = tf.tensor_scatter_nd_max(t14,
indices=[[0, 2], [1, 1], [2, 0]],
updates=[6, 5, 4])
print(t16)
tf.Tensor( [[-2 -7 6] [-9 5 1] [ 4 -3 -8]], shape=(3, 3), dtype=int32)
Lectures complémentaires et ressources
Dans ce guide, vous avez appris à utiliser les opérations de découpage des tenseurs disponibles avec TensorFlow pour exercer un contrôle plus précis sur les éléments de vos tenseurs.
Découvrez les opérations de découpage disponibles avec TensorFlow NumPy telles que
tf.experimental.numpy.take_along_axis
ettf.experimental.numpy.take
.Consultez également le guide Tensor et le guide Variable .