👥 Broadcasting (NumPy)
Le Broadcasting est une fonctionnalité puissante de NumPy qui permet d'effectuer des opérations arithmétiques (, , , ...) sur des tableaux de dimensions différentes.
Sans broadcasting, pour additionner deux tableaux, ils doivent avoir exactement les mêmes dimensions. Le broadcasting relâche cette contrainte en "étirant" implicitement le tableau le plus petit pour qu'il corresponde à la taille du plus grand.
Exemple simple : scalaire + vecteur
Le cas le plus simple est l'addition d'un nombre (scalaire) à un vecteur.
import numpy as np
vec = np.array([1, 2, 3])
resultat = vec + 4
print(resultat)
# [5 6 7]
Ce qui se passe "sous le capot" :
NumPy "imagine" que le 4 est en fait un vecteur [4, 4, 4] de même taille que vec, puis effectue l'addition élément par élément.
Les règles du Broadcasting
Pour que deux ndarray soient compatibles pour le broadcasting, NumPy compare leurs dimensions en partant de la droite (de la dernière dimension vers la première).
Deux dimensions sont compatibles si :
- Elles sont égales, OU
- L'une d'elles vaut 1.
Si des dimensions de gauche (les premières) manquent à l'un des deux ndarray, elles seront rajoutées et le broadcasting aura lieu sur celles-ci.
Si ces conditions ne sont pas remplies, vous obtiendrez une erreur ValueError: operands could not be broadcast together.
Voici quelques exemples pour illustrer les différents cas d'application de ces règles 🕵️:
ndarrayde 'shape': compatible avec , le résultat serandarrayde 'shape': compatible avec , le résultat serandarrayde 'shape': non compatible avec (le broadcasting ne rajoute pas de dimension à droite)ndarrayde 'shape': compatible avec , le résultat serandarrayde 'shape': compatible avec , le résultat sera
Exemple : Vecteur + Matrice
Supposons que nous ayons une matrice de notes (3 étudiants, 4 examens) et que nous voulions ajouter des points bonus différents pour chaque examen.
import numpy as np
# Matrice 3x4 (3 étudiants, 4 examens)
notes = np.array([
[70, 80, 85, 90],
[60, 75, 80, 85],
[90, 95, 90, 99]
])
# Bonus pour les 4 examens (taille 4)
bonus = np.array([2, 5, 0, 1])
# Addition grâce au broadcasting
notes_finales = notes + bonus
Analyse des dimensions
notes:bonus:
Les dernières dimensions (4 et 4) correspondent. NumPy va "broadcaster" le vecteur bonus sur chaque rangée de la matrice notes.
Résultat :
[[72 85 85 91 ] <-- [70+2, 80+5, 85+0, 90+1]
[62 80 80 86 ] <-- [60+2, 75+5, 80+0, 85+1]
[92 100 90 100]] <-- [90+2, 95+5, 90+0, 99+1]
Attention à l'ordre des dimensions (utilité de reshape)
Si on veut ajouter un bonus individuel à chaque étudiant (donc par rangée), il faut faire attention à l'ordre des dimensions.
import numpy as np
notes = np.array([[70, 80], [60, 75]]) # (2, 2)
bonus_etudiant = np.array([5, 10]) # (2,)
# Résultat non correct car (2,) s'aligne sur la dernière dimension donc sur les examens au lieu des étudiants
# notes + bonus_etudiant
# array([[75, 90],
# [65, 85]])
Pour que le "broadcasting" s'applique sur les rangées, il faut transformer le vecteur 1D en colonne (2, 1).
import numpy as np
bonus_colonne = bonus_etudiant.reshape(2, 1) # Forme (2, 1)
# notes : (2, 2)
# bonus : (2, 1)
# ^ ^
# | compatible (2 vs 1)
# compatible (2 vs 2)
resultat = notes + bonus_colonne
# [[75, 85], <-- +5 partout
# [70, 85]] <-- +10 partout
Avantages
- Code concis : Pas besoin de boucles
forimbriquées. - Performance : Les opérations sont effectuées en C, beaucoup plus vite que des boucles Python.
- Mémoire : NumPy ne crée pas physiquement les copies des données dupliquées, l'opération est économe en mémoire.