Tenseurs et formes
- Leçon 4
- 50 min
- Module 2 : Les tenseurs et PyTorch
Leçon 4 sur 23 · L'apprentissage profond et les transformeurs expliquésTenseurs et formes
1. Ce qu'est un réseau de neurones
2. Les tenseurs et PyTorch
3. Comment les réseaux de neurones apprennent
4. Diagnostiquer les problèmes d'entraînement
5. Représenter les séquences et le sens
6. Assembler un transformeur
7. Utiliser des modèles préentraînés
8. Sous le capot : les mathématiquesFacultatif
Ce que vous saurez faire
Lisez la forme de chaque tableau de nombres utilisé par un réseau avant d’exécuter le code. Une mauvaise forme arrête le code avec une erreur. Pire encore, elle peut donner une mauvaise réponse sans aucune erreur.
Carnet JupyterFaites cette leçon dans un carnet Jupyter
Le carnet (notebook) Jupyter contient toutes les cellules de code de cette leçon, avec les tâches et les vérifications. Il fonctionne dans Colab ou Kaggle, où PyTorch est déjà installé. Vous n’avez donc rien à installer. Environ 30 minutes.
Le carnet est en anglais. Colab et Kaggle ouvrent votre propre copie. Il faut un compte Google ou Kaggle gratuit. Vous êtes bloqué ? Consultez le carnet de solution.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- Une matrice et sa forme, avec une ligne par observation et une colonne par caractéristique, dans Représenter les observations du cours de mathématiques.
- La règle des formes pour la multiplication matricielle, (n × k) × (k × m) → (n × m), dans Les opérations sur les vecteurs.
- Une couche comme un ensemble de neurones qui lisent les mêmes entrées, dans Neurones et couches, plus tôt dans ce cours.
Ce qu’il vous faut sur votre ordinateur
- Rien pour le carnet Jupyter : il s’ouvre dans Colab ou Kaggle avec un compte gratuit. La prochaine leçon, Installer PyTorch, installe PyTorch sur votre ordinateur, si vous préférez y travailler.
Testé avec Python 3.12 et PyTorch 2.14.1 sur le processeur (CPU), sous macOS.
Œufs, cartons et caisses
Section intitulée « Œufs, cartons et caisses »Imaginez un magasin qui vend des œufs. Un œuf est un seul élément. Une rangée de 6 œufs forme une ligne. Un carton contient 2 rangées de 6. Une caisse contient 10 cartons. Pour décrire une caisse pleine, vous donnez un nombre pour chaque direction : 10 cartons, 2 rangées, 6 œufs. Cela donne 10 × 2 × 6 = 120 œufs.
Le nombre 120 ne suffit pas. Un bon de livraison qui indique « 120 œufs » ne dit pas comment ils sont emballés. Il pourrait s’agir de 20 cartons de 6, ou de 12 rangées de 10. Pour les déballer correctement, il vous faut le nombre dans chaque direction, dans le bon ordre.
Le problème : douze nombres, deux sens
Section intitulée « Le problème : douze nombres, deux sens »Un réseau de neurones rencontre le même problème avec les nombres. Dans le cours de mathématiques, Priya a décrit trois billets de soutien avec quatre caractéristiques chacun. Ces caractéristiques étaient la longueur, les mots liés au remboursement, les billets précédents et un indicateur de photo. Cela fait 12 nombres. PyTorch, la bibliothèque de ce cours, peut les stocker dans une seule longue liste. reshape() découpe la liste en lignes. Ici, cette fonction découpe les mêmes 12 nombres de deux façons :
import torch
flat = torch.tensor([2.0, 2.0, 0.0, 1.0, 1.0, 0.0, 3.0, 0.0, 3.0, 1.0, 1.0, 1.0]) # 12 numbersprint(flat.reshape(3, 4)) # 3 tickets, 4 features eachprint(flat.reshape(4, 3)) # 4 "tickets", 3 "features" eachLa sortie :
tensor([[2., 2., 0., 1.], [1., 0., 3., 0.], [3., 1., 1., 1.]])tensor([[2., 2., 0.], [1., 1., 0.], [3., 0., 3.], [1., 1., 1.]])Le premier tableau est celui de Priya : une ligne pour chaque billet. Le deuxième tableau contient les mêmes nombres, et aucune erreur ne s’affiche. Mais il décrit 4 billets qui n’existent pas. Sa deuxième ligne mélange l’indicateur de photo du billet 1 avec les deux premières caractéristiques du billet 2. Un réseau qui lit ces lignes apprend à partir de données sans sens. Le réseau a donc besoin de plus que les nombres. Il doit savoir comment ils sont disposés.
L’idée : un tenseur est une boîte de nombres avec une forme
Section intitulée « L’idée : un tenseur est une boîte de nombres avec une forme »Un tenseur est une boîte de nombres accompagnée de sa forme : un nombre pour chaque direction. Chaque direction est une dimension. Le mot vient du latin et signifie « étirer ». Les physiciens l’ont d’abord utilisé pour les forces qui étirent un matériau. En apprentissage profond, il désigne un tableau avec un nombre quelconque de dimensions. PyTorch stocke chaque entrée, poids et sortie d’un réseau sous forme de tenseur.
Description textuelle du diagramme
Le schéma montre quatre boîtes de nombres de gauche à droite, ou de haut en bas sur un téléphone. Un scalaire a 0 dimension : une cellule contenant le score 5,5. Sa forme est vide et s’écrit (). Un vecteur a 1 dimension : une rangée de 4 cellules, 2, 2, 0 et 1, les caractéristiques d’un billet. Sa forme est (4,). Une matrice a 2 dimensions : 3 lignes de 4 cellules, les trois billets. Sa forme est (3, 4). Une flèche le long des lignes porte l’étiquette dim 0. Une flèche le long des colonnes porte l’étiquette dim 1. Un tenseur à 3 dimensions contient deux grilles de 3 sur 4, l’une derrière l’autre. Sa forme est (2, 3, 4) : 2 billets, 3 mots chacun, 4 nombres pour chaque mot.
Voici les mêmes quatre tenseurs dans PyTorch. torch.tensor() crée un tenseur à partir de listes Python. torch.zeros() en crée un de la forme donnée, rempli de zéros. t.ndim donne le nombre de dimensions, t.shape donne la forme et t.numel() compte les nombres.
import torch
score = torch.tensor(5.5) # one numberticket = torch.tensor([2.0, 2.0, 0.0, 1.0]) # one ticket: 4 featuresbatch = torch.tensor([[2.0, 2.0, 0.0, 1.0], [1.0, 0.0, 3.0, 0.0], [3.0, 1.0, 1.0, 1.0]]) # 3 tickets, 4 features eachwords = torch.zeros(2, 3, 4) # 2 tickets, 3 words, 4 numbers per word
for name, t in [("score", score), ("ticket", ticket), ("batch", batch), ("words", words)]: print(f"{name:<7} ndim {t.ndim} shape {tuple(t.shape)} numbers {t.numel()}")La sortie :
score ndim 0 shape () numbers 1ticket ndim 1 shape (4,) numbers 4batch ndim 2 shape (3, 4) numbers 12words ndim 3 shape (2, 3, 4) numbers 24Le nombre de valeurs est toujours le produit des tailles : 3 × 4 = 12 et 2 × 3 × 4 = 24. La virgule dans (4,) est la façon dont Python écrit un tuple contenant une seule valeur. PyTorch affiche une forme sous la forme torch.Size, qui fonctionne comme un tuple de nombres entiers :
print(batch.shape)print(batch.shape[0], "tickets,", batch.shape[1], "features")La sortie :
torch.Size([3, 4])3 tickets, 4 featuresLes noms scalaire, vecteur et matrice désignent les cas particuliers à 0, 1 et 2 dimensions. Dans le cours de mathématiques, vous avez vu un tenseur à 3 dimensions sous forme de photo couleur : hauteur × largeur × 3 couleurs. Dans le module 5 de ce cours, chaque mot d’un billet devient une ligne de nombres. Un lot de billets est alors un tenseur à 3 dimensions comme words.
La dimension de lot
Section intitulée « La dimension de lot »Dans batch, chaque ligne est un billet et chaque colonne est une caractéristique. La première dimension, dim 0, compte les billets. Un groupe d’exemples qu’un réseau traite ensemble est un lot. Dim 0 est donc la dimension de lot. La dernière dimension, dim 1, contient les caractéristiques de chaque exemple. C’est la disposition de presque tous les réseaux de ce cours : (lot, caractéristiques).
Pourquoi traiter les billets en lot plutôt qu’un par un? Un seul produit matriciel calcule les scores de tous les billets à la fois. Un ordinateur le fait beaucoup plus vite que plusieurs petits produits. Le code reste le même pour 3 billets ou 3 000.
Faites attention quand vous sélectionnez un billet dans un lot. Un indice supprime la dimension de lot, tandis qu’une tranche la conserve :
print(batch[0], batch[0].shape)print(batch[0:1], batch[0:1].shape)La sortie :
tensor([2., 2., 0., 1.]) torch.Size([4])tensor([[2., 2., 0., 1.]]) torch.Size([1, 4])Les deux contiennent les mêmes quatre nombres. Mais batch[0:1] reste un lot : un lot d’un seul billet. Le code qui attend (lot, caractéristiques) fonctionne avec lui, comme le montre La propagation avant.
Multiplier : la règle des formes que vous connaissez
Section intitulée « Multiplier : la règle des formes que vous connaissez »Une couche d’un réseau calcule des sommes pondérées, comme dans Neurones et couches. Dans PyTorch, @ représente la multiplication matricielle. Voici les poids d’urgence de Priya du cours de mathématiques, un poids pour chaque caractéristique :
w = torch.tensor([0.5, 2.0, 1.0, 0.5]) # one weight per featurescores = batch @ wprint(scores, scores.shape)La sortie :
tensor([5.5000, 3.5000, 5.0000]) torch.Size([3])Le score du premier billet est 2 × 0,5 + 2 × 2 + 0 × 1 + 1 × 0,5 = 5,5. La règle du cours de mathématiques s’applique : les nombres intérieurs doivent être égaux, et les nombres extérieurs donnent le résultat. Maintenant, Tomás veut un score pour chacune des 5 équipes. Il écrit les poids avec une ligne pour chaque équipe :
W = torch.zeros(4, 5) # 4 features in, 5 teams outprint((batch @ W).shape)W_wrong = torch.zeros(5, 4) # one row per teamprint((batch @ W_wrong).shape)La sortie :
torch.Size([3, 5])RuntimeError: mat1 and mat2 shapes cannot be multiplied (3x4 and 5x4)PyTorch appelle les deux matrices mat1 et mat2, et donne leurs deux formes. Les nombres intérieurs sont 4 et 5, donc le produit est impossible. W_wrong.T transpose la matrice : sa forme devient (4, 5), et le produit fonctionne. Lisez chaque erreur de forme de cette façon. Trouvez les deux formes, puis la paire de nombres qui doivent être égaux.
La diffusion : une ligne pour chaque billet
Section intitulée « La diffusion : une ligne pour chaque billet »Un magasin écrit « livraison : 5 € par commande » une seule fois, en haut de sa liste de prix. Personne ne copie 5 € dans chaque ligne du tableau des commandes. Tout le monde comprend que les mêmes frais s’appliquent à chaque commande.
Priya veut faire la même chose avec les tenseurs. Elle veut savoir à quel point chaque billet diffère du billet moyen. Elle calcule donc la moyenne de chaque caractéristique, une ligne de 4 nombres, puis la soustrait de chaque billet. Sans aide, elle doit d’abord copier la ligne 3 fois pour obtenir un tenseur de moyennes de forme (3, 4). Avec 4 696 billets, cette copie contient 4 696 lignes.
PyTorch fait cette copie pour elle, sans stocker les copies. C’est la diffusion (broadcasting) : le petit tenseur est « diffusé » vers le grand, comme un signal radio qui atteint chaque maison. La règle compare les deux formes à partir de la droite, une dimension à la fois. Deux tailles conviennent si elles sont égales, si l’une vaut 1, ou si l’une est absente. Une taille de 1, ou une dimension absente, est étirée pour correspondre à l’autre.
Description textuelle du diagramme
Le schéma montre trois cas côte à côte, ou l’un sous l’autre sur un téléphone. Chaque cas place la forme de batch, 3 et 4, dans deux cases. Ces cases sont au-dessus de la forme d’un deuxième tenseur, alignée à droite. Dans le premier cas, batch moins mean, mean a une case vide en pointillés à gauche et 4 à droite. 4 égale 4, et la dimension absente s’étire à 3. Le résultat est (3, 4). Dans le deuxième cas, batch divisé par totals, totals contient 3 et 1. Le 1 s’étire à 4, et 3 égale 3. Le résultat est (3, 4). Dans le troisième cas, batch divisé par totals_flat, totals_flat contient une case vide et 3. En comparant à partir de la droite, 4 et 3 sont différents, et aucun ne vaut 1. Le résultat est une erreur.
Voici le premier cas. batch.mean(dim=0) calcule la moyenne le long de dim 0, sur les billets. Il reste donc un nombre pour chaque caractéristique :
mean = batch.mean(dim=0) # the mean of each column: shape (4,)print(mean)print(batch - mean) # (3, 4) - (4,)La sortie :
tensor([2.0000, 1.0000, 1.3333, 0.6667])tensor([[ 0.0000, 1.0000, -1.3333, 0.3333], [-1.0000, -1.0000, 1.6667, -0.6667], [ 1.0000, 0.0000, -0.3333, 0.3333]])Vérifiez un nombre. Le billet 2 a 3 billets précédents, et la moyenne est 1,3333, donc 3 − 1,3333 = 1,6667. La diffusion fonctionne aussi le long des colonnes. Ici, les nombres de chaque billet sont divisés par le total de ce billet. keepdim=True conserve la dimension additionnée avec une taille de 1, donc les totaux forment une colonne :
totals = batch.sum(dim=1, keepdim=True) # one total per ticket: shape (3, 1)print(totals)print(batch / totals) # (3, 4) / (3, 1)La sortie :
tensor([[5.], [4.], [6.]])tensor([[0.4000, 0.4000, 0.0000, 0.2000], [0.2500, 0.0000, 0.7500, 0.0000], [0.5000, 0.1667, 0.1667, 0.1667]])Sans keepdim=True, les totaux ont la forme (3,). En comparant à partir de la droite, 4 et 3 ne conviennent pas :
totals_flat = batch.sum(dim=1) # shape (3,): keepdim forgottenprint(totals_flat.shape)print(batch / totals_flat)La sortie :
torch.Size([3])RuntimeError: The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 1Une dimension « non-singleton » est une dimension dont la taille n’est pas 1. Le message nomme les tailles, 4 et 3, et la dimension où elles se rencontrent, dim 1. Prédisez d’abord le résultat, puis essayez chaque opération dans l’explorateur. Dans l’explorateur, W est une plus petite matrice de forme (4, 2), avec deux équipes plutôt que cinq. Ainsi, tous ses nombres tiennent à l’écran.
Explorer
Formes en entrée, forme en sortie
Prédisez d’abord : batch a la forme (3, 4). Quelle est la forme de batch − mean si mean a la forme (4,)? Et que se passe-t-il avec totals_flat, de forme (3,)?
- Forme de batch
- (3, 4)
- Forme de mean
- (4,)
- Résultat
- (3, 4)
Résultat : forme (3, 4). Comparez les formes en partant de la droite : 4 et 4 sont égaux. mean n’a pas de première dimension, donc PyTorch utilise sa seule ligne pour les 3 billets (les copies pâles). Chaque billet montre maintenant son écart par rapport au billet moyen.
batch
(3, 4) float32
| 2 | 2 | 0 | 1 |
| 1 | 0 | 3 | 0 |
| 3 | 1 | 1 | 1 |
mean
(4,) float32
étiré à (3, 4)| 2 | 1 | 1,33 | 0,67 |
| 2 | 1 | 1,33 | 0,67 |
| 2 | 1 | 1,33 | 0,67 |
result
(3, 4) float32
| 0 | 1 | −1,33 | 0,33 |
| −1 | −1 | 1,67 | −0,67 |
| 1 | 0 | −0,33 | 0,33 |
PyTorch affiche
>>> (batch - mean).shape
torch.Size([3, 4])Description textuelle de l’explorateur
L’explorateur contient une rangée de boutons, un pour chaque opération. Les opérations sont batch − mean, batch / totals, batch / totals_flat, batch @ w, batch @ W, batch @ W.T, scores − targets et counts @ w. Pour chacune, il montre les formes en entrée, les tenseurs avec leurs valeurs, le résultat et ce que PyTorch affiche.
batch − mean : (3, 4) et (4,) donnent (3, 4); la ligne de moyennes sert pour les 3 billets. batch / totals : (3, 4) et (3, 1) donnent (3, 4); chaque ligne donne une somme de 1. batch / totals_flat : (3, 4) et (3,) provoquent un arrêt avec une erreur. Le message est « The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 1 ». Il signifie que les tailles 4 et 3 doivent correspondre à la dimension 1, qui n’a pas une taille de 1. batch @ w : (3, 4) et (4,) donnent (3,), les scores 5,5, 3,5 et 5,0. batch @ W, avec W de forme (4, 2) : le résultat est (3, 2). batch @ W.T, avec W.T de forme (2, 4), s’arrête avec « mat1 and mat2 shapes cannot be multiplied (3x4 and 2x4) ». Cela signifie que les formes de mat1 et mat2 ne permettent pas la multiplication. scores − targets : (3,) et (3, 1) donnent (3, 3) sans erreur, une mauvaise réponse qu’explique l’erreur fréquente ci-dessous. counts @ w : les formes conviennent, mais counts contient des nombres entiers et w contient des nombres décimaux. PyTorch s’arrête avec « dot : expected both vectors to have same dtype, but found Long and Float ». Cela signifie que les deux vecteurs doivent avoir le même type, mais que leurs types sont Long et Float.
Quand devriez-vous utiliser la diffusion? Utilisez-la pour les opérations voulues : une ligne de valeurs pour chaque exemple, ou une colonne de valeurs pour chaque caractéristique. Son inconvénient est qu’elle ne demande jamais si c’était votre intention. L’erreur fréquente à la fin de cette leçon montre une forme qui provoque une diffusion accidentelle.
Le type des nombres : dtype
Section intitulée « Le type des nombres : dtype »Chaque tenseur possède aussi un dtype, le type de ses nombres. torch.tensor() crée les nombres entiers en int64 et les nombres décimaux en float32, qui utilise 4 octets par nombre. Les réseaux calculent avec float32. Un produit ne mélange pas les deux types :
counts = torch.tensor([2, 2, 0, 1]) # whole numbersprint(counts.dtype, w.dtype)print(counts @ w)La sortie :
torch.int64 torch.float32RuntimeError: dot : expected both vectors to have same dtype, but found Long and FloatPyTorch appelle int64 « Long » et float32 « Float » dans ses messages. La correction est counts.float() @ w, qui donne tensor(5.5000). Les comptes de mots sont des nombres entiers. La propagation avant les crée donc comme nombres décimaux dès le départ.
Où se trouvent les nombres : l’appareil
Section intitulée « Où se trouvent les nombres : l’appareil »Un tenseur possède aussi un appareil : le matériel dont la mémoire le stocke. Dans ce cours, chaque tenseur se trouve sur le CPU, et print(batch.device) affiche cpu (processeur). Un tenseur peut passer sur une carte graphique avec .to("cuda"). Mais tous les tenseurs d’une même opération doivent se trouver sur le même appareil. La prochaine leçon montre comment vérifier la présence d’une carte graphique. Vous n’en avez pas besoin.
NumPy et PyTorch
Section intitulée « NumPy et PyTorch »Dans le cours d’apprentissage automatique, vos tableaux étaient des tableaux NumPy. torch.from_numpy() transforme un tableau NumPy en tenseur, et .numpy() fait l’inverse. Les deux partagent la même mémoire, donc rien n’est copié. Surveillez le dtype : NumPy crée les nombres décimaux en float64, soit 8 octets chacun, et non en float32.
import numpy as np
from_numpy = torch.from_numpy(np.array([2.0, 2.0, 0.0, 1.0]))print(from_numpy.dtype)print(from_numpy @ w)La sortie :
torch.float64RuntimeError: dot : expected both vectors to have same dtype, but found Double and Float« Double » désigne float64. Écrivez from_numpy.float() @ w, et le résultat est tensor(5.5000). Dans l’autre sens, (batch @ w).numpy() donne le tableau NumPy [5.5 3.5 5. ].
Les billets de Larkfield sous forme de tenseurs
Section intitulée « Les billets de Larkfield sous forme de tenseurs »Passons à la vraie tâche. Dans La propagation avant, chaque billet devient 2 864 nombres, un pour chaque mot d’une liste fixe. Un lot de 8 billets est alors un tenseur de forme (8, 2864). La première couche du réseau transforme 2 864 nombres en 64. Avant d’exécuter du code, lisez les formes : (8, 2864) @ (2864, 64). Les nombres intérieurs correspondent, donc le résultat est (8, 64).
tickets = torch.zeros(8, 2864) # 8 tickets, 2,864 word counts eachW1 = torch.zeros(2864, 64) # 2,864 inputs, 64 outputsprint((tickets @ W1).shape)print(tickets.element_size(), "bytes per number,", tickets.element_size() * tickets.numel(), "bytes in all")print("all 4,696 training tickets:", 4696 * 2864 * 4, "bytes")La sortie :
torch.Size([8, 64])4 bytes per number, 91648 bytes in allall 4,696 training tickets: 53797376 bytesLa forme indique aussi la mémoire nécessaire. Chaque nombre float32 occupe 4 octets, donc le lot de 8 occupe 91 648 octets. Les 4 696 billets d’entraînement occupent environ 54 Mo. Cela tient facilement sur un ordinateur portable. Mais la mémoire augmente avec chaque dimension. Amira exécutera le réseau dans l’application de soutien. Elle demande donc la mémoire nécessaire pour chaque modèle de ce cours.
Quand lire les formes, et ce que cela coûte
Section intitulée « Quand lire les formes, et ce que cela coûte »Lisez les formes avant d’exécuter le code, chaque fois que deux tenseurs se rencontrent. Cela inclut un produit, +, −, * ou /, et l’entrée d’un tenseur dans une couche. Écrivez la forme attendue dans un commentaire, comme le fait le code de cette leçon. Affichez x.shape en cas de doute. Cette habitude coûte quelques secondes. Elle évite les heures perdues à cause d’une mauvaise forme qui ne provoque aucune erreur. Les formes ne disent pas tout. Deux tenseurs aux bonnes formes peuvent quand même contenir les mauvais nombres, comme les douze nombres du début l’ont montré.
Exercices guidés : les formes dans le carnet Jupyter
Section intitulée « Exercices guidés : les formes dans le carnet Jupyter »- Ouvrez le carnet Jupyter dans l’encadré Faites cette leçon dans un carnet Jupyter, en haut de cette page.
- Exécutez les cellules de configuration. La première affiche une ligne qui commence par
PyTorch 2.. - Dans la section 1, créez les quatre tenseurs. Vous voyez les formes
(),(4,),(3, 4)et(2, 3, 4). - Dans la section 2, prédisez la forme de
batch[0]et debatch[0:1]. Exécutez ensuite la cellule. Vous voyeztorch.Size([4])ettorch.Size([1, 4]). - Dans la section 3, calculez
scores = batch @ w. Vous voyeztensor([5.5000, 3.5000, 5.0000]). - Dans la section 4, prédisez laquelle des trois cellules de diffusion provoque une erreur. Exécutez-les ensuite. Seule
batch / totals_flaten provoque une. - Dans la cellule Your turn (à vous), calculez
centered: chaque billet moins la moyenne de chaque caractéristique. Exécutez ensuite la cellule de vérification. Elle afficheCheck passed.(vérification réussie).
Afficher un exemple de réponse à l’étape 7
centered = batch - batch.mean(dim=0)print(centered.shape)torch.Size([3, 4])batch.mean(dim=0) a la forme (4,), une moyenne pour chaque caractéristique. La diffusion l’utilise pour chacun des 3 billets, donc le résultat a la forme de batch.
À vous de jouer : cinq billets
Section intitulée « À vous de jouer : cinq billets »Changez une seule chose : le lot contient maintenant 5 billets, five = torch.ones(5, 4). Avant d’exécuter quoi que ce soit, notez la forme de five @ w, de five - five.mean(dim=0) et de five / five.sum(dim=1, keepdim=True). Vérifiez ensuite vos réponses dans le carnet Jupyter.
Afficher la réponse
five = torch.ones(5, 4) # 5 tickets, 4 featuresprint((five @ w).shape)print((five - five.mean(dim=0)).shape)print((five / five.sum(dim=1, keepdim=True)).shape)torch.Size([5])torch.Size([5, 4])torch.Size([5, 4])Seule la dimension du lot a changé, passant de 3 à 5. Les poids, les moyennes et les caractéristiques ont toujours 4 nombres, donc le même code fonctionne. Voilà pourquoi le lot vient en premier : le code ne dépend pas du nombre de billets.
Erreur courante
L'erreur qui ne s'affiche pas
Symptôme : Priya compare les trois scores aux scores attendus par Grace : 5, 4 et 5. Elle calcule l’erreur absolue moyenne, présentée dans Les métriques de régression du cours Apprentissage automatique : du problème à un modèle fiable. Elle s’attend à environ 0,3. Elle obtient ceci, sans message d’erreur :
targets = torch.tensor([[5.0], [4.0], [5.0]]) # one column: shape (3, 1)errors = scores - targets # (3,) - (3, 1)print(errors.shape)print(errors)print("mean absolute error:", round(errors.abs().mean().item(), 3))torch.Size([3, 3])tensor([[ 0.5000, -1.5000, 0.0000], [ 1.5000, -0.5000, 1.0000], [ 0.5000, -1.5000, 0.0000]])mean absolute error: 0.778Cause : scores a la forme (3,) et targets a la forme (3, 1). En comparant depuis la droite, 3 rencontre 1, puis une dimension absente rencontre 3. Les deux tenseurs s’étendent. PyTorch soustrait donc chaque cible de chaque score : 9 différences au lieu de 3. La moyenne de ces 9 différences n’est pas l’erreur des billets.
Correction : rendez les deux formes identiques avant de faire la soustraction. targets.squeeze(1) supprime la dimension de taille 1 :
targets = targets.squeeze(1) # remove the dimension of size 1: shape (3,)errors = scores - targetsprint(errors.shape, errors)print("mean absolute error:", round(errors.abs().mean().item(), 3))torch.Size([3]) tensor([ 0.5000, -0.5000, 0.0000])mean absolute error: 0.333Ce que cela signifie pour un vrai système d’IA : une diffusion accidentelle des dimensions donne un nombre qui semble normal. Une erreur de 0,778 paraît crédible. Rien ne plante, et le mauvais nombre se retrouve dans un rapport ou dans l’entraînement. Affichez la forme de chaque résultat dont vous ne prévoyiez pas de changement. Vérifiez qu’elle correspond à la forme indiquée dans votre commentaire.
Vérification des connaissances
Section intitulée « Vérification des connaissances »Vérifiez votre compréhension
Un tenseur a la forme (16, 2864). Expliquez ce que chaque nombre signifie pour un lot de billets. Combien de nombres contient-il, et combien d'octets occupent-ils en float32?
Afficher la réponse
16 est la dimension du lot : 16 billets. 2 864 est la dimension des caractéristiques : 2 864 nombres par billet, un pour chaque entrée de la liste de mots. Le tenseur contient 16 × 2 864 = 45 824 nombres. Chaque nombre float32 occupe 4 octets. Ils occupent donc 183 296 octets, soit environ 0,18 Mo.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Prédisez la forme du résultat, ou une erreur, pour chaque paire : (8, 2864) @ (2864, 64); (8, 64) + (64,); (8, 64) + (8,); (8, 5) - (8, 1).
Afficher la réponse
- (8, 2864) @ (2864, 64) → (8, 64) : les nombres intérieurs sont égaux.
- (8, 64) + (64,) → (8, 64) : depuis la droite, 64 = 64, et la dimension absente s’étend à 8. C’est ainsi qu’une couche ajoute son biais à chaque billet.
- (8, 64) + (8,) → erreur : depuis la droite, 64 rencontre 8. Ils ne sont pas égaux, et aucun des deux ne vaut 1.
- (8, 5) − (8, 1) → (8, 5) : depuis la droite, 1 s’étend à 5, et 8 = 8. Un nombre par billet est soustrait de chacun de ses 5 scores.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Tomás dit : « Si les formes étaient incorrectes, PyTorch me le dirait. » Utilisez cette leçon pour expliquer quand c'est vrai et quand ce ne l'est pas.
Afficher la réponse
C’est vrai quand aucune règle ne peut rendre les formes compatibles. Par exemple, un produit avec des nombres intérieurs différents, ou deux tailles différentes dont aucune ne vaut 1. PyTorch s’arrête alors et indique les deux formes. Ce n’est pas vrai lorsque la diffusion peut étendre un tenseur. Des scores de forme (3,) moins des cibles de forme (3, 1) donnent un tableau (3, 3), sans erreur. L’erreur absolue moyenne est alors de 0,778 au lieu de 0,333. PyTorch vérifie que les formes sont compatibles. Il ne peut pas vérifier qu’elles représentent ce que vous vouliez. Lisez donc les formes avant d’exécuter le code, puis affichez-les après.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Un tenseur est une boîte de nombres avec une forme : un nombre d’éléments pour chaque dimension. Un scalaire a la forme (), un vecteur (4,), une matrice (3, 4), un tenseur à trois dimensions (2, 3, 4).
- Dans un réseau, la première dimension est habituellement le lot : (lot, caractéristiques).
batch[0]la supprime;batch[0:1]la conserve. @multiplie les matrices : les nombres intérieurs doivent être égaux. Le message de PyTorch indique les deux formes : « mat1 and mat2 shapes cannot be multiplied (3x4 and 5x4) » (impossible de multiplier les formes de mat1 et mat2).- La diffusion compare les formes depuis la droite. Des tailles égales, un 1 ou une dimension absente sont compatibles; un 1 ou une dimension absente s’étend. Cette extension peut aussi se produire par accident, sans erreur : (3,) − (3, 1) donne (3, 3).
- Chaque tenseur a un type de données (
float32pour les réseaux,int64pour les nombres entiers,float64venant de NumPy) et un périphérique (le processeur dans ce cours). Une opération exige le même type de données et le même périphérique pour tous ses tenseurs.
Ensuite, vous installez PyTorch sur votre ordinateur, ou vous le vérifiez dans Colab. Puis vous exécutez un premier programme et comparez sa sortie, nombre par nombre.
Leçon suivante : Installer PyTorch