Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 74

PyTorch Tensors: Creation, Manipulation, and Device Management

Recommended resources

Bonjour et bienvenue dans cette nouvelle étape de votre parcours en deep learning ! Dans la leçon précédente, nous avons exploré l'héritage en programmation orientée objet, un concept clé qui vous a montré comment créer des classes spécialisées (enfants) à partir de classes plus générales (parentes). Vous avez vu un aperçu de la manière dont cette idée est fondamentale dans PyTorch pour construire des modèles de réseaux de neurones en héritant de torch.nn.Module.

Aujourd'hui, nous plongeons directement au cœur de PyTorch en nous concentrant sur son élément de base : le tenseur. L'objectif de cette leçon est de vous apprendre à créer et manipuler des tenseurs dans PyTorch, y compris à changer leur périphérique de calcul (CPU/GPU). Considérez les tenseurs comme les briques fondamentales avec lesquelles vous construirez toutes vos architectures de deep learning. Maîtriser leur manipulation est une compétence essentielle.

1. Qu'est-ce qu'un tenseur PyTorch ?

Si vous avez travaillé avec NumPy, l'idée d'un tenseur vous semblera familière. Un tenseur est essentiellement un tableau multi-dimensionnel de nombres. C'est la structure de données centrale de PyTorch.

Vous pouvez vous représenter les tenseurs de différentes dimensions de la manière suivante :

  • Un scalaire (un seul nombre) est un tenseur de 0 dimension.
  • Un vecteur (une séquence de nombres) est un tenseur de 1 dimension.
  • Une matrice (un tableau de nombres à deux dimensions) est un tenseur de 2 dimensions.
  • Et ainsi de suite pour des dimensions supérieures.
Cette image montre des exemples de tenseurs PyTorch de 0, 1, 2 et 3 dimensions, ainsi que le code pour les créer. Un simple nombre est un tenseur 0D, une liste est un tenseur 1D, une liste de listes est un tenseur 2D, et ainsi de suite.

Alors, pourquoi utiliser les tenseurs PyTorch plutôt que les tableaux NumPy, que vous connaissez déjà ? L'article suivant de datagy explique les deux avantages principaux.

PyTorch Tensors: The Ultimate Guide • datagy

Cet article offre une excellente introduction aux tenseurs PyTorch.

Lisez la section d'introduction, en particulier la partie intitulée "What are PyTorch Tensors?". Concentrez-vous sur les points qui différencient les tenseurs des tableaux NumPy, notamment l'accélération par GPU et la différenciation automatique (autograd).

Comme vous l'avez lu, les deux super-pouvoirs des tenseurs PyTorch sont :

  1. Accélération par GPU : Les tenseurs peuvent être déplacés de manière transparente sur une unité de traitement graphique (GPU), ce qui accélère massivement les calculs numériques complexes requis pour l'entraînement des réseaux de neurones.
  2. Différenciation automatique : PyTorch peut automatiquement calculer les gradients (dérivées) des opérations effectuées sur les tenseurs. C'est le moteur de l'algorithme de descente de gradient que nous utiliserons pour entraîner nos modèles.

2. Création de tenseurs

PyTorch offre de nombreuses façons de créer des tenseurs. La méthode la plus simple est de convertir une structure de données Python existante, comme une liste.

import torch




# Créer un tenseur à partir d'une liste
list_data = [[1, 2, 3], [4, 5, 6]]
my_tensor = torch.tensor(list_data)

print(my_tensor)



# Output:
# tensor([[1, 2, 3],
#         [4, 5, 6]])

La vidéo suivante de la chaîne officielle de PyTorch vous montrera visuellement plusieurs de ces méthodes de création.

Introduction to PyTorch Tensors

Cette vidéo est une excellente introduction pratique à la création de tenseurs.

Regardez la première partie, de l'importation de PyTorch jusqu'à la fin de la section sur la création de tenseurs à partir de collections Python. Elle couvre torch.empty, torch.zeros, torch.ones, torch.rand et torch.tensor.

En résumé, voici les méthodes les plus courantes pour créer des tenseurs :

  • torch.tensor(data) : Crée un tenseur à partir de données Python (listes, tuples).
  • torch.zeros(shape) : Crée un tenseur rempli de zéros avec la forme (shape) spécifiée.
  • torch.ones(shape) : Crée un tenseur rempli de uns.
  • torch.rand(shape) : Crée un tenseur avec des valeurs aléatoires entre 0 et 1.
  • torch.from_numpy(numpy_array) : Crée un tenseur à partir d'un tableau NumPy. Il est important de noter que le tenseur et le tableau NumPy partageront la même mémoire sous-jacente, donc un changement dans l'un affectera l'autre.

3. Attributs et manipulations des tenseurs

Une fois qu'un tenseur est créé, vous pouvez inspecter ses propriétés et le manipuler. Trois attributs sont particulièrement importants : .shape, .dtype, et .device.

PyTorch Tensors: The Ultimate Guide • datagy

Continuons avec le guide de datagy pour explorer les attributs et les opérations de base.

Parcourez les sections suivantes : Attributs des tenseurs : Pour comprendre .shape, .dtype, et .device. Types de données : Pour voir comment spécifier et changer le dtype. Opérations sur les tenseurs : Pour découvrir les opérations arithmétiques de base. Indexation et découpage : Qui fonctionne comme avec les listes Python et les tableaux NumPy. Remodelage des tenseurs : Pour apprendre à utiliser .T, .view(), et .reshape().

Explorons ces points avec des exemples de code.

Attributs essentiels




# Créons un tenseur pour l'exemple
data = torch.rand(size=(2, 3), dtype=torch.float32)




# .shape : La forme (dimensions) du tenseur
print(f"Shape: {data.shape}")  # Output: Shape: torch.Size([2, 3])




# .dtype : Le type de données des éléments
print(f"Dtype: {data.dtype}")  # Output: Dtype: torch.float32




# .device : Le périphérique où le tenseur est stocké
print(f"Device: {data.device}") # Output: Device: cpu

La forme (shape) est cruciale. Une erreur de forme est l'une des erreurs les plus courantes en deep learning. L'image suivante illustre comment les dimensions de la forme correspondent à la structure imbriquée du tenseur.

Cette image montre comment `dim=0`, `dim=1`, et `dim=2` correspondent aux niveaux des listes imbriquées dans un tenseur 3D. La `torch.Size` qui en résulte reflète le nombre d'éléments à chaque niveau.

Opérations et manipulations

L'indexation, le découpage et les opérations arithmétiques de base sur les tenseurs PyTorch sont très similaires à ce que vous avez appris avec les listes Python et les tableaux NumPy.




# Création de deux tenseurs
tensor_a = torch.tensor([[1, 2], [3, 4]])
tensor_b = torch.ones(2, 2) # Tenseur 2x2 rempli de 1




# Addition
sum_tensor = tensor_a + tensor_b
print(f"Addition:\n{sum_tensor}\n")




# Multiplication (élément par élément)
product_tensor = tensor_a * 2
print(f"Multiplication par un scalaire:\n{product_tensor}\n")




# Indexation (comme les listes Python)
print(f"Première ligne: {tensor_a[0]}\n")




# Découpage (slicing)
print(f"Première colonne: {tensor_a[:, 0]}\n")




# Remodelage (Reshaping) avec .view()
# .view() change la "vue" du tenseur sans changer les données sous-jacentes
flat_tensor = tensor_a.view(4) # Aplatit le tenseur en 1D
print(f"Tenseur aplati: {flat_tensor}")

4. Déplacer les tenseurs entre CPU et GPU

C'est ici que réside l'un des plus grands avantages de PyTorch. L'entraînement de grands modèles est beaucoup plus rapide sur un GPU. PyTorch facilite grandement le transfert de vos données et de votre modèle vers le GPU si vous en avez un.

La pratique standard consiste à écrire du code "agnostique au périphérique" (device-agnostic), qui fonctionnera que vous ayez un GPU ou non.




# Vérifier si un GPU (CUDA est l'architecture de NVIDIA) est disponible
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")

Une fois que vous avez défini votre device, vous pouvez y déplacer n'importe quel tenseur en utilisant la méthode .to().

Introduction to PyTorch Tensors

Cette section de la vidéo est consacrée au déplacement des tenseurs vers un accélérateur matériel.

Regardez cette partie cruciale qui explique comment vérifier la disponibilité d'un GPU et y déplacer des tenseurs. Elle montre comment créer un tenseur directement sur le GPU et comment utiliser la méthode .to() pour déplacer un tenseur existant.

Voici comment cela fonctionne en pratique :




# Créer un tenseur sur le CPU par défaut
tensor_cpu = torch.tensor([[1., 2.], [3., 4.]])
print(f"Tenseur sur le CPU: {tensor_cpu.device}")




# Déplacer le tenseur vers le périphérique défini (GPU si disponible)
tensor_gpu = tensor_cpu.to(device)
print(f"Tenseur déplacé vers: {tensor_gpu.device}")




# Il est crucial que tous les tenseurs impliqués dans une opération
# soient sur le même périphérique.
# La ligne suivante lèverait une erreur si `device` est "cuda":
# result = tensor_cpu + tensor_gpu

Cette simple méthode .to(device) est la clé pour exploiter la puissance des GPU. Vous l'utiliserez non seulement pour vos données (tenseurs), mais aussi pour vos modèles de réseaux de neurones.


Conclusion

Félicitations ! Vous avez fait vos premiers pas avec la structure de données la plus importante de PyTorch. Cette base est indispensable pour tout ce qui va suivre.

Points clés à retenir :

  • Les tenseurs sont des tableaux multi-dimensionnels, similaires aux tableaux NumPy, mais avec des capacités d'accélération GPU et de différenciation automatique.
  • Vous pouvez créer des tenseurs de plusieurs manières : torch.tensor(), torch.rand(), torch.ones(), etc.
  • Les attributs essentiels d'un tenseur sont sa forme (.shape), son type de données (.dtype) et le périphérique sur lequel il se trouve (.device).
  • La manipulation des tenseurs (indexation, découpage, remodelage) suit des conventions similaires à celles de NumPy.
  • La méthode .to(device) est utilisée pour déplacer des tenseurs entre le CPU et le GPU, une étape cruciale pour des performances optimales.

Dans la prochaine leçon, nous approfondirons la manipulation des tenseurs en explorant des opérations mathématiques plus avancées, telles que le produit matriciel, qui sont au cœur des calculs effectués à l'intérieur d'un réseau de neurones.