En 1969, cette limite a mis la recherche en IA en pause pendant 15 ans. La solution n'était pas un neurone plus intelligent — c'était d'en empiler plusieurs.
Un seul neurone, c'est une seule feuille de papier posée à plat : on peut la couper d'un coup de ciseau, en une seule ligne droite. Empiler une deuxième couche de neurones, c'est plier cette feuille avant de la couper — la même coupe droite dessine désormais une forme brisée sur le papier déplié.
Un neurone seul ne peut séparer que ce qu'une ligne droite sépare. Un réseau de neurones peut plier l'espace autant de fois qu'il a de couches.
Le problème s'appelle XOR ("ou exclusif") : la classe est vraie quand exactement une des deux entrées vaut 1 — jamais les deux, jamais aucune. Minsky et Papert ont montré en 1969 qu'un perceptron seul ne peut pas l'apprendre.
>>> table_verite_XOR [(0,0) -> 0, (0,1) -> 1, (1,0) -> 1, (1,1) -> 0] # 4 points, 2 classes, aucune ligne droite ne les sépare >>> perceptron.entrainer(XOR) >>> perceptron.precision 0.75 # un point reste toujours mal classé, quoi qu'on fasse >>> reseau_2_couches.entrainer(XOR) >>> reseau_2_couches.precision 1.00 # les 4 points, correctement séparés
Cette limite a suffi à convaincre le monde académique que les réseaux de neurones étaient une impasse. Les financements se sont taris — c'est le premier "hiver de l'IA". Il aura fallu attendre les années 1980 pour comprendre que la solution était déjà sous la main : empiler une deuxième couche.
En clair : la solution n'était pas un neurone plus intelligent, c'était d'en empiler plusieurs. Ce principe — une seule couche trace une ligne, plusieurs couches combinées découpent l'espace en formes complexes — est le socle qui a mené, des décennies plus tard, jusqu'aux réseaux profonds et aux transformers d'aujourd'hui.
Les points noirs et roses sont les 4 points du problème XOR posés sur la feuille. La ligne pointillée est la coupe — toujours parfaitement droite. Ce qui change, c'est la feuille elle-même.
Choisissez le nombre de neurones cachés, cliquez sur Entraîner. C'est une vraie descente de gradient qui tourne dans votre navigateur — poids aléatoires au départ, ajustés pas à pas jusqu'à convergence (ou jusqu'à blocage).
Faux si on oublie un détail : empiler des couches qui ne font que des sommes pondérées, sans rien d'autre, ne sert à rien. Une couche linéaire appliquée à une couche linéaire reste... une couche linéaire.
Le vrai ingrédient : ce qui permet à un réseau de plier l'espace, ce n'est pas le nombre de couches en soi, c'est la fonction d'activation non-linéaire entre chaque couche (sigmoïde, ReLU...). Sans elle, 10 couches empilées équivalent mathématiquement à une seule — et on retombe sur la même ligne droite qu'un simple perceptron. C'est exactement le sujet du prochain épisode.
Le même principe que le simulateur, en Python avec NumPy — un perceptron seul contre un petit réseau à 2 couches.
import numpy as np # Les 4 points du problème XOR X = np.array([[0,0],[0,1],[1,0],[1,1]]) y = np.array([0,1,1,0]) def sigmoid(z): return 1 / (1 + np.exp(-z)) # Réseau à 1 couche cachée (ici : 2 neurones) — résout XOR W1 = np.random.randn(2, 2); b1 = np.zeros(2) W2 = np.random.randn(2, 1); b2 = np.zeros(1) for epoch in range(10000): h = sigmoid(X @ W1 + b1) # couche cachée pred = sigmoid(h @ W2 + b2) # couche de sortie # ... rétropropagation du gradient (backprop) ... print(f"précision finale : {precision:.0%}") # 100%