NumPy : dis adieu aux boucles, ton Python va 50 fois plus vite

NumPy : dis adieu aux boucles, ton Python va 50 fois plus vite

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom": "numpy", "version": "2.x"}

Difficulté

Débutant

Tu crois faire de l'IA ? En réalité, sous chaque réseau de neurones, chaque modèle de machine learning et chaque pipeline de données se cache la même brique : NumPy. C'est le socle sur lequel reposent Pandas, scikit-learn, PyTorch et TensorFlow. Comprendre NumPy, c'est apprendre le langage commun de tout l'écosystème data et IA.

Mais il y a une raison encore plus concrète de s'y intéresser : la vitesse. Une opération écrite « à la NumPy » s'exécute de 50 à 100 fois plus vite qu'une boucle Python classique. La clé s'appelle la vectorisation. On va la démonter ensemble, avec du code que tu peux copier-coller tel quel.

Étape 1 — Installer NumPy et créer ton premier tableau

NumPy s'installe comme n'importe quelle bibliothèque Python, via pip :

bash
pip install numpy

Le cœur de NumPy, c'est le ndarray, un tableau multidimensionnel. On le crée en une ligne à partir d'une simple liste Python :

python
import numpy as np

# Une liste Python classique
notes = [12, 15, 9, 18, 11]

# Le même tableau, version NumPy
arr = np.array(notes)
print(arr)          # [12 15  9 18 11]
print(arr.dtype)    # int64
print(arr.shape)    # (5,)

Rien de spectaculaire pour l'instant. Note au passage le dtype : contrairement à une liste Python qui mélange les types, un ndarray est homogène, ce qui permet à NumPy de stocker les données de façon contiguë en mémoire et de les lire à toute vitesse. La magie commence quand on abandonne les boucles.

NumPy fournit aussi tout un arsenal pour générer des tableaux sans les taper à la main : np.zeros(5) pour cinq zéros, np.ones(3) pour des uns, np.linspace(0, 1, 11) pour onze points régulièrement espacés entre 0 et 1, ou encore np.random.rand(1000) pour mille nombres aléatoires. Tu en auras besoin en permanence, autant les connaître dès maintenant.

Étape 2 — La vectorisation : bye bye les boucles

Imagine que tu veuilles multiplier deux listes de cinq millions de nombres, élément par élément. En Python pur, tu écris une boucle. Avec NumPy, tu écris simplement a * b. Comparons les deux :

python
import numpy as np
import time

N = 5_000_000

# Version Python pur, avec une boucle
a_py = list(range(N))
b_py = list(range(N))
start = time.perf_counter()
c_py = [a_py[i] * b_py[i] for i in range(N)]
t_py = time.perf_counter() - start

# Version NumPy, vectorisée
a_np = np.arange(N)
b_np = np.arange(N)
start = time.perf_counter()
c_np = a_np * b_np
t_np = time.perf_counter() - start

print(f"Python pur : {t_py:.3f} s")
print(f"NumPy      : {t_np:.3f} s")
print(f"NumPy est {t_py / t_np:.0f} fois plus rapide")

Sur ma machine, la boucle Python met environ 0,4 seconde, NumPy 8 millisecondes : un facteur 50. Pourquoi une telle différence ? Parce que Python interprète chaque tour de boucle un par un, alors que NumPy délègue le calcul à du code C optimisé qui traite tout le tableau d'un seul coup. Moins d'allers-retours entre Python et la machine, moins de temps perdu. Retiens la règle d'or : dès que tu peux remplacer une boucle par une opération sur le tableau entier, fais-le.

Étape 3 — Indexer, découper, filtrer

NumPy ne sert pas qu'à accélérer les calculs : il rend aussi l'accès aux données beaucoup plus expressif. Le découpage (slicing) fonctionne comme sur les listes, avec un bonus redoutable : les masques booléens.

python
import numpy as np

arr = np.arange(1, 11)   # [1 2 3 ... 10]
print(arr[0])            # 1
print(arr[-1])           # 10
print(arr[2:5])          # [3 4 5]

# Masque booléen : tous les éléments > 5
print(arr[arr > 5])      # [6 7 8 9 10]

# Piège : une tranche est une VUE, pas une copie
vue = arr[2:5]
vue[0] = 999
print(arr)  # [1 2 999 4 5 6 7 8 9 10]

Attention au piège classique : une tranche de tableau NumPy est une vue sur les données d'origine, pas une copie. Modifie la tranche, et tu modifies le tableau de départ. Pour une copie réellement indépendante, utilise .copy().

Étape 4 — Tableaux à deux dimensions et broadcasting

La plupart des données (images, tableurs, matrices) vivent en deux dimensions. NumPy les manipule naturellement grâce à reshape :

python
import numpy as np

mat = np.arange(1, 10).reshape(3, 3)
print(mat)
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]

# Ajouter 10 à chaque élément, sans boucle (broadcasting)
print(mat + 10)

# Moyenne par ligne (axis=1) et par colonne (axis=0)
print(mat.mean(axis=1))  # [2. 5. 8.]
print(mat.mean(axis=0))  # [4. 5. 6.]

La vraie star de l'étape, c'est le broadcasting : la capacité de NumPy à combiner des tableaux de tailles différentes sans écrire la moindre boucle. Ajouter un scalaire à une matrice, soustraire un vecteur à chaque ligne, tout se fait automatiquement, à condition que les dimensions soient compatibles. C'est ce qui rend le code à la fois court et lisible.

Dernier conseil de pro : pour de gros volumes, choisis ton dtype avec soin. Un tableau en float32 occupe deux fois moins de mémoire qu'en float64, ce qui compte quand on manipule des millions d'éléments ou qu'on prépare des données pour un modèle.

Étape 5 — Un exemple qui sent le machine learning

On assemble tout dans un cas concret : une régression linéaire, le grand-père de tous les modèles d'IA. On connaît des tailles (en cm) et des poids (en kg), et on veut prédire le poids à partir de la taille. Avec la méthode des moindres carrés, ça tient en quelques lignes, sans la moindre boucle :

python
import numpy as np

# Données : taille (cm) -> poids (kg)
X = np.array([150, 160, 170, 180, 190])
y = np.array([50, 60, 68, 80, 90])

# Régression linéaire par moindres carrés
Xb = np.column_stack([np.ones_like(X), X])
coefs = np.linalg.lstsq(Xb, y, rcond=None)[0]
print(f"poids = {coefs[0]:.1f} + {coefs[1]:.2f} * taille")

# Prédiction pour 175 cm
pred = coefs[0] + coefs[1] * 175
print(f"Prédiction pour 175 cm : {pred:.1f} kg")

Voilà un vrai modèle de machine learning en cinq lignes, et une prédiction pour 175 cm qui tombe pile dans le plausible. Ce n'est pas un gadget : c'est exactement ce genre d'algèbre linéaire que PyTorch et TensorFlow exécutent en coulisses, à une échelle gigantesque.

Ce qu'il faut retenir, c'est la mécanique : un tableau homogène, des opérations par lot, et du C optimisé en dessous. C'est ce trio qui fait de NumPy la fondation de tout le reste, et c'est lui qui te permettra de lire le code de n'importe quelle bibliothèque d'IA sans paniquer.

NumPy est la brique de base de tout l'écosystème IA. Apprendre à vectoriser tes calculs, c'est écrire du code plus court, plus lisible et radicalement plus rapide. Commence par remplacer une seule de tes boucles aujourd'hui : tu ne reviendras plus en arrière.