Chapitre 5 · 16 min
Un neurone qui apprend
Construis un neurone entraînable, dérive son gradient et ajoute la première étape d’apprentissage à ton code local.
Nous avons maintenant des , des et une mesure de similarité. Il nous manque encore quelque chose qui apprend. Le du chapitre 1 était entraîné par comptage ; ce n’est pas vraiment apprendre, c’est tenir une comptabilité. Pour aller plus loin, il faut une fonction dont les changent en réponse à ses erreurs.
Un est la plus petite fonction de ce genre. Il prend un vecteur, le pondère, somme, ajoute un biais, puis passe par une non-linéarité :
Cette ligne est l’histoire entière des réseaux feed-forward. Plusieurs en parallèle donnent une couche ; plusieurs couches donnent un réseau profond. Commençons par un seul.
1. La passe avant
Écris la fonction qui prend x = [x_0, x_1], des w = [w_0, w_1], un biais b, et retourne la sortie du . La est fournie.
Code · JavaScript
Les barres montrent la sortie du pour plusieurs entrées. Avec w = [1, 0.5] et b = 0, les points où w · x + b est positif doivent produire une sortie > 0.5. Le est juste une somme pondérée suivie d’un écrasement ; le reste du chapitre sert à ajuster w et b automatiquement.
2. La fonction de loss
Avec la sortie p du et la vraie étiquette y (0 ou 1), il nous faut un nombre qui dit “à quel point cette prédiction était mauvaise”. Le choix standard est la binary :
Elle est proche de zéro quand p correspond à y, et grande quand le modèle est confiant dans le mauvais sens. Ajoute un petit epsilon avant les logs pour éviter log(0).
Code · JavaScript
Les barres montrent la pour plusieurs couples (prédiction, étiquette). Quand ça correspond, la est petite ; quand ça diverge, surtout avec confiance, elle explose.
3. Le gradient
La composition + binary a une propriété magnifique : le de la par rapport à (w · x + b) vaut simplement p - y. Autrement dit, l’erreur elle-même est le . Ensuite :
Écris la fonction de . Le chapitre compare ta sortie à une référence.
Code · JavaScript
Si la comparaison affiche ✓, ton correspond à la forme fermée. C’est le petit lemme qui rend la régression logistique et les réseaux neuronaux pratiques.
4. Entraîner le neurone
On assemble tout. Utilise un dataset de deux clusters en 2D, itère la et regarde la frontière de décision se placer.
Code · JavaScript
Le scatter à gauche montre les données ; la ligne orange est la frontière w · x + b = 0, où la sortie du vaut 0.5. Après , la ligne doit passer entre les deux clusters. La courbe à droite est la au fil du temps : elle doit descendre puis se stabiliser.
5. Ajouter le premier pas d’apprentissage localement
Crée llm/nn.py :
"""Small neural-network pieces before the PyTorch rewrite."""
from __future__ import annotations
import math
# [1]
def sigmoid(x: float) -> float:
return 1.0 / (1.0 + math.exp(-x))
# [2]
def neuron(x: list[float], w: list[float], b: float) -> float:
return sigmoid(sum(xi * wi for xi, wi in zip(x, w)) + b)
# [3]
def bce(pred: float, target: float) -> float:
eps = 1e-12
pred = min(max(pred, eps), 1.0 - eps)
return -(target * math.log(pred) + (1.0 - target) * math.log(1.0 - pred))
def neuron_step(
x: list[float],
target: float,
w: list[float],
b: float,
lr: float,
) -> tuple[list[float], float, float]:
pred = neuron(x, w, b)
# [4]
error = pred - target
# [5]
next_w = [wi - lr * error * xi for wi, xi in zip(w, x)]
next_b = b - lr * error
return next_w, next_b, bce(pred, target)Lis le pas comme une boucle d’ minuscule :
- [1]
sigmoidramène tout score entre 0 et 1. - [2]
neuroncalcule somme pondérée + biais, puis une sortie de type probabilité. - [3]
bcepunit fort les mauvaises réponses confiantes. - [4]
error = pred - targetest la simplification clé. - [5] met à jour et biais contre cette erreur.
C’est le premier fichier de ton projet qui modifie des à cause d’une erreur. Cette idée monte jusqu’au chapitre 13.
Ce que le neurone ne peut pas faire
Sur des données non linéairement séparables, le échoue. Aucune droite ne peut isoler un cercle intérieur d’un cercle extérieur. Un seul est fondamentalement un classifieur linéaire avec une en sortie.
C’est la limite que le chapitre 6 attaque : un fait une ligne ; une couche de fait plusieurs lignes et les combine.
Recap
- Un est une somme pondérée suivie d’une non-linéarité. - La mesure l’erreur.
Binary + est le couple standard. - Le vaut
(p - y) * xpour les . - L’ est une répétée. - Ton projet local a maintenantllm/nn.pyavec un entraînable. - Limite : un seul ne sait apprendre qu’une frontière linéaire.
Pour aller plus loin
- Appendice · La backprop à la main — dérive les du même type de réseau pas à pas, puis vérifie contre
loss.backward(). Optionnel mais recommandé si « d’où viennent les gradients ? » reste flou. - Karpathy, “Building micrograd”.
- La série réseaux neuronaux de 3Blue1Brown.
- Les implémentations de référence vivent dans
lib/ml/nn/{linear,activations,loss}.ts.
Prochaine étape : empiler les couches — un fait une ligne ; plusieurs peuvent sculpter beaucoup plus.