NumPy Indexation & Découpage : Comment découper un tenseur à volonté

1. Pourquoi l’indexation/découpage est-elle si importante ?



En deep‑learning, on manipule des tenseurs à maintes reprises.

  • Extraire seulement les premiers échantillons d’un batch
  • Sélectionner un canal particulier (R/G/B) d’une image
  • Couper certaines étapes temporelles d’une séquence
  • Isoler une classe spécifique dans les labels

Toutes ces opérations se résument à l’indexation et le découpage.

La syntaxe d’indexation/découpage de Tensor en PyTorch est pratiquement identique à celle de NumPy, donc maîtriser NumPy facilite grandement la rédaction de code deep‑learning.


2. Indexation de base : du 1D au 2D

2.1 Indexation d’un tableau 1D

import numpy as np

x = np.array([10, 20, 30, 40, 50])

print(x[0])  # 10
print(x[1])  # 20
print(x[4])  # 50
  • Les indices commencent à 0
  • x[i] renvoie l’élément i‑ème

2.2 Indexation négative

Pour compter depuis la fin, on utilise les indices négatifs.

print(x[-1])  # 50 (dernier)
print(x[-2])  # 40

PyTorch fonctionne de la même façon.


3. Découpage de base : start:stop:step



Le découpage s’écrit x[start:stop:step].

x = np.array([10, 20, 30, 40, 50])

print(x[1:4])    # [20 30 40], 1 ≤ i < 4
print(x[:3])     # [10 20 30], de 0 à 3
print(x[2:])     # [30 40 50], de 2 à la fin
print(x[:])      # copie complète

En ajoutant step, on introduit un intervalle.

print(x[0:5:2])  # [10 30 50], 0 à 4 pas de 2
print(x[::2])    # [10 30 50], même chose

En deep‑learning, on saute souvent des pas de temps ou on sélectionne des échantillons à intervalles réguliers.


4. Indexation 2D et plus : lignes et colonnes

Les tableaux 2D correspondent à des matrices/batchs, donc le sens deep‑learning apparaît.

import numpy as np

X = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])  # shape: (3, 3)

4.1 Indexation d’une seule ligne/colonne

print(X[0])      # première ligne : [1 2 3]
print(X[1])      # deuxième ligne : [4 5 6]

print(X[0, 0])   # ligne 1, colonne 1 : 1
print(X[1, 2])   # ligne 2, colonne 3 : 6
  • X[i] → i‑ème ligne (1D)
  • X[i, j] → valeur scalaire à (i, j)

4.2 Découpage de lignes

print(X[0:2])    # lignes 0 et 1
# [[1 2 3]
#  [4 5 6]]

print(X[1:])     # lignes 1 à la fin
# [[4 5 6]
#  [7 8 9]]

C’est le pattern typique pour couper les premiers ou derniers échantillons d’un batch.

4.3 Découpage de colonnes

print(X[:, 0])   # toutes les lignes, colonne 0 → [1 4 7]
print(X[:, 1])   # toutes les lignes, colonne 1 → [2 5 8]
  • : signifie « tout le dimension »
  • X[:, 0] signifie « toutes les lignes, colonne 0 »

En deep‑learning :

  • Dans un tableau (batch_size, feature_dim), on extrait une feature : X[:, k]

5. 3D et plus : batch × canal × hauteur × largeur

Prenons l’exemple d’images.

# (batch, height, width) supposé
images = np.random.randn(32, 28, 28)  # 32 images 28×28

5.1 Extraire un seul échantillon

img0 = images[0]        # première image, shape: (28, 28)
img_last = images[-1]   # dernière image

5.2 Utiliser une partie du batch

first_8 = images[:8]    # 8 premiers, shape: (8, 28, 28)

5.3 Découper une région d’une image (crop)

# centre 20×20
crop = images[:, 4:24, 4:24]  # shape: (32, 20, 20)

En PyTorch :

# images_torch: (32, 1, 28, 28) supposé
center_crop = images_torch[:, :, 4:24, 4:24]

Le concept d’indexation/découpage est pratiquement le même.


6. Le découpage donne généralement une vue (view)

Un point clé :

Le résultat d’un découpage est généralement une vue de l’array d’origine. Cela signifie qu’il ne s’agit pas d’une copie, mais d’une fenêtre sur les données originales.

x = np.array([10, 20, 30, 40, 50])
y = x[1:4]   # vue

print(y)     # [20 30 40]
y[0] = 999

print(y)     # [999  30  40]
print(x)     # [ 10 999  30  40  50]  ← l’original a changé !

Avantages : mémoire et vitesse. Inconvénients : risque de modifier l’original.

Pour créer une copie indépendante, utilisez copy().

x = np.array([10, 20, 30, 40, 50])
y = x[1:4].copy()

y[0] = 999
print(x)  # [10 20 30 40 50], l’original reste intact

PyTorch possède un concept similaire, donc garder la distinction vue vs copie aide au débogage.


7. Indexation booléenne : filtrer par condition

L’indexation booléenne permet de sélectionner les éléments qui satisfont une condition.

import numpy as np

x = np.array([1, -2, 3, 0, -5, 6])

mask = x > 0
print(mask)      # [ True False  True False False  True]

pos = x[mask]
print(pos)       # [1 3 6]
  • x > 0 → tableau de True/False
  • x[mask] → éléments où la valeur est True

Exemple combiné :

X = np.array([[1, 2, 3],
              [4, 5, 6],
              [-1, -2, -3]])

pos = X[X > 0]
print(pos)  # [1 2 3 4 5 6]

En deep‑learning, on l’utilise souvent pour :

  • Extraire les échantillons qui répondent à une condition (ex : label = 1)
  • Appliquer un masque lors du calcul de la perte pour ne prendre en compte que certaines valeurs

PyTorch fonctionne de façon identique :

import torch

x = torch.tensor([1, -2, 3, 0, -5, 6])
mask = x > 0
pos = x[mask]

8. Indexation par tableau d’entiers / liste (Fancy Indexing)

On peut sélectionner plusieurs positions à la fois avec un tableau ou une liste d’indices.

x = np.array([10, 20, 30, 40, 50])

idx = [0, 2, 4]
print(x[idx])  # [10 30 50]

En 2D :

X = np.array([[1, 2],
              [3, 4],
              [5, 6]])  # shape: (3, 2)

rows = [0, 2]
print(X[rows])  
# [[1 2]
#  [5 6]]

En deep‑learning :

  • Sélectionner aléatoirement des échantillons d’un batch
  • Rassembler des labels ou prédictions à des positions spécifiques

PyTorch supporte le même style.


9. Patterns d’indexation courants

Voici les patterns les plus fréquents en deep‑learning :

import numpy as np

# (batch, feature)
X = np.random.randn(32, 10)

# 1) Les 8 premiers échantillons
X_head = X[:8]              # (8, 10)

# 2) Une feature particulière (ex : colonne 3)
f3 = X[:, 3]                # (32,)

# 3) Échantillons à indices pairs
X_even = X[::2]             # (16, 10)

# 4) Échantillons dont le label est 1
labels = np.random.randint(0, 3, size=(32,))
mask = labels == 1
X_cls1 = X[mask]            # échantillons label 1

# 5) Mélanger puis séparer train/val
indices = np.random.permutation(len(X))
train_idx = indices[:24]
val_idx = indices[24:]

X_train = X[train_idx]
X_val = X[val_idx]

Ces patterns se traduisent presque directement en tensors PyTorch. En maîtrisant l’indexation NumPy, on acquiert la capacité de découper, mélanger et sélectionner les données de façon fluide.


10. Conclusion

En résumé :

  • Indexation : x[i], x[i, j], indices négatifs
  • Découpage : start:stop:step, :, indexation multidimensionnelle (X[:, 0], X[:8], X[:, 4:8])
  • Le découpage donne une vue : modifier la vue modifie l’original → utilisez copy() si besoin
  • Indexation booléenne : filtrer par condition (x[x > 0], X[labels == 1])
  • Indexation par tableau d’entiers : sélectionner plusieurs positions d’un coup (x[[0,2,4]])

Maîtriser ces techniques vous permet de manipuler les tensors PyTorch pour couper des batches, choisir des canaux, appliquer des masques ou mélanger des échantillons de façon simple et rapide.

image