Ismail Ben Alla

MyTorcha

Un framework de deep learning écrit de zéro

Deep learning · mars 2024 · Terminé

Un framework de deep learning reconstruit à partir des premiers principes : de l'autograd aux LSTM et à l'attention, chaque gradient vérifié.

Construit avecPythonNumPypytestPyTorch

MyTorcha — vue d’ensemble

Présentation

Des frameworks comme PyTorch réduisent l'entraînement d'un réseau à un appel, ce qui en cache aussi le fonctionnement. MyTorcha retire cette couche : chaque gradient est du code que j'ai écrit et un test qui le vérifie, avec NumPy pour seule dépendance.

Tout a commencé par un moteur d'autograd scalaire, où chaque nombre est un nœud d'un graphe de calcul. Cette version est conservée comme chapitre pédagogique. C'est aussi la raison pour laquelle le framework a gagné un second moteur : une seule couche 784-vers-10 construit 31 427 nœuds scalaires par image. Le moteur Tensor applique la même règle de dérivation en chaîne à des tableaux entiers, ce qui rend les modèles convolutifs, récurrents et à attention praticables sur un CPU.

Le reconstruire a d'abord voulu dire tester l'original. Les vérifications par différences finies ont révélé de vrais bugs dans la v1 : une dérivée du log fausse d'un facteur d'environ 3, des nœuds qui étaient égaux par valeur et se retrouvaient fusionnés en silence pendant la rétropropagation, et un état d'optimiseur partagé entre tous les poids. Chacun est aujourd'hui un test de régression.

La question

Est-ce que je comprends assez bien le deep learning pour reconstruire un framework, de l'autograd aux LSTM et à l'attention, dont les gradients coïncident avec ceux de PyTorch ?

Fonctionnalités clés

Comment ça marche

  1. Chaque opération enregistre ses entrées

    Une opération calcule son tableau de sortie et stocke une fonction qui transforme le gradient de la sortie en un gradient par entrée.

  2. backward() parcourt le graphe

    Un tri topologique itératif ordonne le graphe ; les gradients circulent en sens inverse et sont sommés sur les dimensions diffusées par broadcasting.

  3. Les couches sont des Modules

    Un Module trouve ses Parameters en parcourant ses attributs, de sorte qu'un CNN ou un LSTM n'est que du Python ordinaire composé de briques testées.

  4. Vérifié deux fois

    Chaque règle de rétropropagation est comparée aux différences finies en float64, et la passe avant comme la passe arrière de chaque couche à celles de PyTorch.

Exemples

Entrée

cnn = nn.Sequential(nn.Conv2d(1, 8, 3, padding=1), nn.BatchNorm2d(8), nn.ReLU(), nn.MaxPool2d(2), ..., nn.Linear(784, 10)); mt.Trainer(cnn, nn.CrossEntropyLoss(), optim.Adam(cnn.parameters(), lr=2e-3)).fit(train_loader, epochs=3, val_loader=val_loader)

Sortie

Validation accuracy 94.35%, 96.70%, 97.10% over 3 epochs (9,146 parameters; an MLP with 101,770 parameters reaches 93.65%).

examples/03_digits_mlp_vs_cnn.py sur 10k images d'entraînement et 2k images de validation du CSV des chiffres Kaggle.

Entrée

model = CharLSTM(vocab); 300 Adam steps on a short text

Sortie

step 0: 'the dbveclgk stmap,sed d ahylb...' -> step 100: 'the chain rule walks that memory backwards.'

examples/05_char_lstm.py : un modèle de langage Embedding + LSTM entraîné de zéro.

Stack technique

Ce que j’ai appris

Limites