Qu’est-ce qu’un réseau de neurones ?
Un réseau de neurones artificiel est un modèle mathématique inspiré du fonctionnement du cerveau humain. Il est composé de « neurones » artificiels organisés en couches, qui apprennent à reconnaître des patterns dans les données. C’est la technologie qui permet à ChatGPT de comprendre le langage, à Google Photos de reconnaître des visages, et à Tesla de conduire de manière autonome. Comprendre son fonctionnement est essentiel pour quiconque travaille dans le domaine de l’IA.
Le neurone artificiel : l’unité de base
Un neurone artificiel fonctionne en trois étapes simples : il reçoit des entrées, les combine et produit une sortie.
Visualisation d'un neurone artificiel :
Entrée 1 (x₁) ──── poids w₁ ────┐
│
Entrée 2 (x₂) ──── poids w₂ ────┼──→ [ Σ + biais ] ──→ [ Activation f() ] ──→ Sortie
│
Entrée 3 (x₃) ──── poids w₃ ────┘
Formule : sortie = f(w₁·x₁ + w₂·x₂ + w₃·x₃ + biais)
Analogie concrète :
Imaginez que vous décidez d'acheter un téléphone à Sandaga (Dakar).
- Entrée 1 : prix (x₁ = 85 000 FCFA, poids w₁ = 0.4 → très important)
- Entrée 2 : marque (x₂ = Samsung, poids w₂ = 0.3 → important)
- Entrée 3 : état batterie (x₃ = 90%, poids w₃ = 0.3 → important)
- Biais : votre tendance générale à acheter = -0.2 (plutôt prudent)
Score = 0.4 × 0.85 + 0.3 × 0.9 + 0.3 × 0.9 + (-0.2) = 0.68
Activation (seuil > 0.5) → Décision : ACHETER ✓
Les fonctions d’activation
La fonction d’activation déterminé si un neurone « s’activé » ou non. Sans elle, le réseau ne pourrait résoudre que des problèmes linéaires (tracer une ligne droite). Les fonctions d’activation introduisent la non-linéarité qui permet au réseau d’apprendre des relations complexes.
Les principales fonctions d'activation :
1. SIGMOID : écrase la valeur entre 0 et 1
σ(x) = 1 / (1 + e^(-x))
Entrée : -5 -2 0 2 5
Sortie : 0.01 0.12 0.50 0.88 0.99
Forme : ___________
/
/
___________/
Usage : couche de sortie pour classification binaire (oui/non)
2. ReLU (Rectified Linear Unit) : le plus utilisé
f(x) = max(0, x)
Entrée : -5 -2 0 2 5
Sortie : 0 0 0 2 5
Forme : /
/
/
____________/
Usage : couches cachées — simple et efficace
3. SOFTMAX : transforme en probabilités (somme = 1)
Entrée : [2.0, 1.0, 0.1]
Sortie : [0.66, 0.24, 0.10] → total = 1.00
Usage : couche de sortie pour classification multi-classes
Exemple : "Cette image est un chat (66%), un chien (24%), un oiseau (10%)"
Architecture d’un réseau de neurones
Un réseau de neurones est composé de couches empilées. Chaque couche contient plusieurs neurones qui traitent les données en parallèle.
Architecture d'un réseau à 3 couches :
COUCHE D'ENTRÉE COUCHE CACHÉE 1 COUCHE CACHÉE 2 COUCHE DE SORTIE
(vos données) (extraction) (combinaison) (résultat)
○ x₁ ─────────────── ○ ─────────────── ○ ─────────────── ○ Chat (0.85)
│ ╲ ╱ │ ╲ ╱ │ ╲ ╱
│ ╲ ╱ │ ╲ ╱ │ ╲ ╱
○ x₂ ──╳──────╳──── ○ ───╳──────╳── ○ ───╳──────╳── ○ Chien (0.12)
│ ╱ ╲ │ ╱ ╲ │ ╱ ╲
│ ╱ ╲ │ ╱ ╲ │ ╱ ╲
○ x₃ ─────────────── ○ ─────────────── ○ ─────────────── ○ Oiseau (0.03)
3 neurones 4 neurones 4 neurones 3 neurones
(pixels, valeurs) (détails simples) (formes complexes) (probabilités)
Chaque trait (─) représente un poids (nombre) que le réseau apprend.
Total de poids dans cet exemple : 3×4 + 4×4 + 4×3 = 40 paramètrès
GPT-4 en a environ 1 800 000 000 000 (1.8 trillion) !
Comment un réseau apprend : la rétropropagation
L’apprentissage d’un réseau de neurones se fait en quatre étapes qui se répètent des milliers de fois sur les données d’entraînement.
LE PROCESSUS D'APPRENTISSAGE (4 étapes) :
ÉTAPE 1 : PROPAGATION AVANT (Forward Pass)
Les données traversent le réseau de gauche à droite.
Image de chat → [réseau avec poids aléatoires] → Prédiction : "Chien" (0.7)
→ Erreur !
ÉTAPE 2 : CALCUL DE L'ERREUR (Loss)
On compare la prédiction avec la bonne réponse.
Prédiction : Chien (0.7), Chat (0.2), Oiseau (0.1)
Réalité : Chien (0.0), Chat (1.0), Oiseau (0.0)
Erreur = Σ(prédiction - réalité)² = 0.49 + 0.64 + 0.01 = 1.14
→ L'erreur est élevée, le réseau se trompe beaucoup.
ÉTAPE 3 : RÉTROPROPAGATION (Backpropagation)
L'erreur est propagée en arrière pour identifier quels poids ont causé l'erreur.
Couche sortie ← "Le neurone Chat doit augmenter, Chien doit diminuer"
Couche cachée 2 ← "Ces neurones doivent ajuster leurs poids de X%"
Couche cachée 1 ← "Ces neurones doivent ajuster leurs poids de Y%"
(C'est du calcul différentiel : dérivées partielles / gradient)
ÉTAPE 4 : MISE À JOUR DES POIDS (Gradient Descent)
Chaque poids est ajusté proportionnellement à sa contribution à l'erreur.
w_nouveau = w_ancien - taux_apprentissage × gradient
Exemple : w = 0.5 - 0.01 × (-0.34) = 0.5034
Après 1000 répétitions sur des milliers d'images :
Image de chat → [réseau entraîné] → Prédiction : "Chat" (0.97) ✓
Implémentation en Python avec NumPy
Voici un réseau de neurones minimal construit à partir de zéro, sans bibliothèque de deep learning. Ce code illustre concrètement tout ce que nous avons expliqué :
import numpy as np
# Fonction d'activation sigmoid et sa dérivée
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
return x * (1 - x)
# Données d'entraînement : porte logique XOR
# Le XOR est le test classique — impossible à résoudre sans couche cachée
X = np.array([
[0, 0],
[0, 1],
[1, 0],
[1, 1]
])
y = np.array([[0], [1], [1], [0]]) # XOR : vrai si les entrées diffèrent
# Initialisation aléatoire des poids
np.random.seed(42)
poids_couche1 = np.random.randn(2, 4) * 0.5 # 2 entrées → 4 neurones cachés
biais_couche1 = np.zeros((1, 4))
poids_couche2 = np.random.randn(4, 1) * 0.5 # 4 neurones cachés → 1 sortie
biais_couche2 = np.zeros((1, 1))
taux_apprentissage = 1.0
erreurs = []
# Entraînement : 10 000 itérations
for epoch in range(10000):
# --- ÉTAPE 1 : Propagation avant ---
couche_cachee = sigmoid(np.dot(X, poids_couche1) + biais_couche1)
sortie = sigmoid(np.dot(couche_cachee, poids_couche2) + biais_couche2)
# --- ÉTAPE 2 : Calcul de l'erreur ---
erreur = y - sortie
mse = np.mean(erreur ** 2)
erreurs.append(mse)
# --- ÉTAPE 3 : Rétropropagation ---
d_sortie = erreur * sigmoid_derivative(sortie)
erreur_cachee = d_sortie.dot(poids_couche2.T)
d_cachee = erreur_cachee * sigmoid_derivative(couche_cachee)
# --- ÉTAPE 4 : Mise à jour des poids ---
poids_couche2 += couche_cachee.T.dot(d_sortie) * taux_apprentissage
biais_couche2 += np.sum(d_sortie, axis=0, keepdims=True) * taux_apprentissage
poids_couche1 += X.T.dot(d_cachee) * taux_apprentissage
biais_couche1 += np.sum(d_cachee, axis=0, keepdims=True) * taux_apprentissage
if epoch % 2000 == 0:
print(f"Epoch {epoch:5d} | Erreur MSE : {mse:.6f}")
# Résultat final
print(f"
Résultats après entraînement :")
print(f"[0,0] → {sortie[0][0]:.4f} (attendu : 0)")
print(f"[0,1] → {sortie[1][0]:.4f} (attendu : 1)")
print(f"[1,0] → {sortie[2][0]:.4f} (attendu : 1)")
print(f"[1,1] → {sortie[3][0]:.4f} (attendu : 0)")
# Sortie :
# Epoch 0 | Erreur MSE : 0.274190
# Epoch 2000 | Erreur MSE : 0.125384
# Epoch 4000 | Erreur MSE : 0.007283
# Epoch 6000 | Erreur MSE : 0.002841
# Epoch 8000 | Erreur MSE : 0.001672
# [0,0] → 0.0234 (attendu : 0) ✓
# [0,1] → 0.9753 (attendu : 1) ✓
# [1,0] → 0.9749 (attendu : 1) ✓
# [1,1] → 0.0312 (attendu : 0) ✓
Les types de réseaux de neurones
CNN — Réseaux convolutifs (vision)
Architecture d'un CNN pour la reconnaissance d'images :
Image (224×224×3)
│
▼
┌─────────────────┐
│ CONVOLUTION 1 │ 32 filtres 3×3 — détecte les bords, lignes, textures
│ + ReLU + Pool │ Sortie : 112×112×32
└────────┬────────┘
│
┌────────▼────────┐
│ CONVOLUTION 2 │ 64 filtres 3×3 — détecte les formes (yeux, roues, lettres)
│ + ReLU + Pool │ Sortie : 56×56×64
└────────┬────────┘
│
┌────────▼────────┐
│ CONVOLUTION 3 │ 128 filtres 3×3 — détecte les objets partiels
│ + ReLU + Pool │ Sortie : 28×28×128
└────────┬────────┘
│
┌────────▼────────┐
│ APLATIR │ 28×28×128 = 100 352 neurones
│ (Flatten) │
└────────┬────────┘
│
┌────────▼────────┐
│ COUCHE DENSE │ 512 neurones — combine les features
│ + ReLU │
└────────┬────────┘
│
┌────────▼────────┐
│ SORTIE │ Chat: 0.92, Chien: 0.05, Oiseau: 0.03
│ (Softmax) │
└─────────────────┘
Usage : reconnaissance d'images, détection d'objets, OCR, imagerie médicale
RNN/LSTM — Réseaux récurrents (séquences)
Architecture d'un RNN pour le traitement de texte :
Phrase : "Le Sénégal est un beau pays"
"Le" "Sénégal" "est" "un" "beau" "pays"
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐
│RNN│─h₁──→│RNN│─h₂──→│RNN│─h₃─→│RNN│─h₄─→│RNN│─h₅─→│RNN│──→ Sortie
└───┘ └───┘ └───┘ └───┘ └───┘ └───┘
h₁, h₂... = "mémoire" : chaque cellule transmet un résumé de ce qu'elle
a lu jusqu'ici. Quand le réseau lit "pays", il se souvient de "Sénégal".
Problème : la mémoire s'estompe sur les longues séquences.
Solution : LSTM (Long Short-Term Memory) avec une "cellule mémoire"
qui peut retenir l'information sur de longues distances.
Usage : traduction, analyse de sentiment, génération de texte,
prédiction de séries temporelles (cours de bourse, météo)
Transformer — L’architecture derrière ChatGPT
Architecture simplifiée d'un Transformer :
Phrase : "Comment créer un site web au Sénégal ?"
┌──────────────────────────────────────┐
│ TOKENISATION │
│ "Comment" "créer" "un" "site" "web" │
│ "au" "Sénégal" "?" │
└──────────────┬───────────────────────┘
│
┌──────────────▼───────────────────────┐
│ EMBEDDING + POSITION │
│ Chaque mot → vecteur de 768 nombres │
│ + position dans la phrase │
└──────────────┬───────────────────────┘
│
┌──────────────▼───────────────────────┐
│ SELF-ATTENTION (la clé !) │
│ │
│ Chaque mot "regarde" tous les autres │
│ pour comprendre le contexte : │
│ │
│ "site" ← forte attention → "web" │
│ "site" ← forte attention → "Sénégal"│
│ "créer" ← forte attention → "site" │
│ │
│ Le mot "Sénégal" change le sens de │
│ toute la phrase (hébergement local, │
│ domaine .sn, contexte africain) │
└──────────────┬───────────────────────┘
│
┌──────────────▼───────────────────────┐
│ FEED-FORWARD + NORMALISATION │
│ × 12 à 96 couches empilées │
└──────────────┬───────────────────────┘
│
┌──────────────▼───────────────────────┐
│ SORTIE │
│ Génère le prochain mot le plus │
│ probable, un par un : │
│ "Pour" "créer" "un" "site"... │
└──────────────────────────────────────┘
Tailles typiques :
- GPT-3 : 96 couches, 175 milliards de paramètrès
- GPT-4 : ~120 couches, ~1.8 trillion de paramètrès (estimé)
- Mistral 7B : 32 couches, 7 milliards de paramètrès
- LLaMA 3 70B : 80 couches, 70 milliards de paramètrès
Construire un réseau avec PyTorch
Voici un exemple concret de classification d’images avec PyTorch, le framework le plus utilisé en recherche et en production :
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# 1. Préparer les données (MNIST : chiffres manuscrits)
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_data = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_data = datasets.MNIST('./data', train=False, transform=transform)
train_loader = DataLoader(train_data, batch_size=64, shuffle=True)
test_loader = DataLoader(test_data, batch_size=64)
# 2. Définir le réseau de neurones
class ReseauClassification(nn.Module):
def __init__(self):
super().__init__()
self.couches = nn.Sequential(
nn.Flatten(), # 28×28 → 784
nn.Linear(784, 256), # Couche cachée 1
nn.ReLU(),
nn.Dropout(0.2), # Régularisation
nn.Linear(256, 128), # Couche cachée 2
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(128, 10) # 10 classes (chiffres 0-9)
)
def forward(self, x):
return self.couches(x)
# 3. Configurer l'entraînement
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = ReseauClassification().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
# 4. Entraîner
for epoch in range(5):
model.train()
total_loss = 0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
output = model(images)
loss = criterion(output, labels)
loss.backward() # Rétropropagation
optimizer.step() # Mise à jour des poids
total_loss += loss.item()
print(f"Epoch {epoch+1}/5 | Loss : {total_loss/len(train_loader):.4f}")
# 5. Évaluer
model.eval()
correct = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
output = model(images)
correct += (output.argmax(1) == labels).sum().item()
accuracy = correct / len(test_data) * 100
print(f"Précision sur le test : {accuracy:.1f}%")
# Résultat typique : 97.5% de précision
Hyperparamètrès clés à comprendre
Taux d’apprentissage (learning rate) : contrôle la taille des ajustements de poids à chaque itération. Trop élevé (0.1) : le réseau oscille et ne converge pas. Trop faible (0.00001) : l’entraînement est très lent. Valeur typique : 0.001. C’est l’hyperparamètre le plus important à ajuster.
Nombre d’époques : combien de fois le réseau voit l’intégralité des données d’entraînement. Trop peu : le modèle n’a pas assez appris (sous-apprentissage). Trop : le modèle mémorise les données d’entraînement sans généraliser (surapprentissage). Surveillez l’erreur sur les données de validation pour trouver le bon nombre.
Taille du batch : combien d’exemples le réseau traite avant de mettre à jour ses poids. Batch de 32 : mises à jour fréquentes, apprentissage bruité mais rapide. Batch de 256 : mises à jour plus stables mais nécessite plus de mémoire GPU. Valeurs courantes : 16, 32, 64, 128.
Dropout : pendant l’entraînement, désactive aléatoirement un pourcentage de neurones (typiquement 20-50%). Force le réseau à ne pas dépendre d’un seul chemin, améliorant la généralisation. C’est comme si un étudiant apprenait à résoudre un problème sans avoir toujours accès à sa calculatrice — il développe une compréhension plus profonde.