Aller au contenu
The loss curve

Guide

Tutoriel LLM en PyTorch — du fichier vide au GPT fonctionnel

Un tutoriel LLM complet en PyTorch — le modèle en ~150 lignes, la boucle d'entraînement, l'optimiseur, l'échantillonnage. Du fichier vide au GPT qui tourne.

Ce guide est une porte d'entrée dans la partie PyTorch de The Loss Curve — les chapitres où le projet passe du JavaScript dans le navigateur à un vrai LLM local en PyTorch. Si tu es arrivé ici en cherchant « tutoriel LLM PyTorch », commence par cette page, puis suis les chapitres dans l'ordre.

1. La forme du code

À la fin de la partie PyTorch, ton projet my-llm/ contient :

my-llm/
├── llm/
│   ├── tokenizer.py    # le BPE entraîné au chapitre 3
│   ├── model.py        # le modèle GPT (~150 lignes)
│   └── train.py        # la boucle d'entraînement
├── data/
│   ├── train.bin       # données d'entraînement tokenisées
│   └── val.bin
└── checkpoints/
    └── ckpt.pt         # poids entraînés

Des fichiers simples. Du PyTorch simple. Rien d'exotique.

2. Préparer le jeu de données

Le chapitre 11 — préparer un dataset charge un corpus, le tokenise avec le tokenizer BPE entraîné plus tôt, construit une séparation train/validation, et sauvegarde les tokens sur disque.

La boucle d'entraînement lit train.bin directement via numpy.memmap : efficace, sans copie, et ça passe à l'échelle sur des corpus plus gros que la RAM.

3. Le modèle

Le chapitre 12 — le code minimal écrit tout le modèle :

class GPT(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.token_emb = nn.Embedding(config.vocab_size, config.n_embd)
        self.pos_emb = nn.Embedding(config.block_size, config.n_embd)
        self.blocks = nn.ModuleList([Block(config) for _ in range(config.n_layer)])
        self.ln_f = nn.LayerNorm(config.n_embd)
        self.head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
        self.head.weight = self.token_emb.weight   # partage de poids
 
    def forward(self, idx, targets=None):
        ...

Le Block est une attention multi-têtes plus un feed-forward, avec résidus et LayerNorm. Chaque pièce a été construite à la main aux chapitres 8 à 10 ; le chapitre 12 est la passe de mise au propre.

4. La boucle d'entraînement

Le chapitre 13 — la boucle d'entraînement écrit la boucle :

for step in range(max_steps):
    x, y = get_batch("train")
    logits, loss = model(x, y)
    optimizer.zero_grad(set_to_none=True)
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
    optimizer.step()
 
    if step % eval_interval == 0:
        val_loss = estimate_loss("val")
        save_checkpoint(model, optimizer, step, val_loss)

Avec AdamW, clipping du gradient, validation périodique et checkpoints propres. Le chapitre visualise la courbe de loss pendant l'exécution.

5. La génération

Le chapitre 14 — génération et échantillonnage écrit l'échantillonneur. Un modèle entraîné n'est qu'une fonction qui transforme une séquence de tokens en distribution sur le token suivant ; la façon dont tu échantillonnes cette distribution fait toute la différence entre un générateur utile et un générateur ennuyeux.

6. Charger de vrais poids

Le chapitre 15 — charger les poids GPT-2 démontre que ton architecture est identique à GPT-2 small : la même classe GPT peut charger les 124M de paramètres d'OpenAI, à l'aide d'une table de correspondance de noms.

C'est là que le cours paie le plus concrètement. Tu as écrit l'architecture. Tu l'as entraînée sur tes données. Maintenant le même code fait tourner un vrai modèle de son époque.

7. Le fine-tuning

À partir d'ici, le reste du cours consiste à rendre un modèle de base utile :

8. Les autres tutoriels PyTorch

À connaître :

  • nanoGPT de Karpathy — plus dense, plus rapide, optimisé pour entraîner de plus gros modèles sur du matériel modeste.
  • minGPT — la version antérieure de Karpathy, encore plus lisible.
  • The Annotated Transformer — le classique, en encodeur-décodeur plutôt qu'en décodeur seul.

The Loss Curve est plus étalé que tous ces projets : il prend son temps et explique chaque pièce. C'est l'arbitrage assumé.

Questions fréquentes

Quel niveau de PyTorch faut-il ?

Être à l'aise avec `nn.Module`, `forward`, `optim` et une boucle d'entraînement de base. Si tu sais écrire un MLP qui s'entraîne sur MNIST, tu peux suivre : chaque notion propre aux Transformers est expliquée au fil du texte.

Pourquoi ~150 lignes ? Ça ne pourrait pas être plus court ?

Si, en densifiant. Le cours optimise la lisibilité : des fonctions séparées pour l'attention, le bloc et le modèle, et une passe avant explicite que tu peux suivre à l'œil. Des implémentations plus courtes existent (le nanoGPT de Karpathy, par exemple) ; celle-ci est faite pour être lue.

Quelle version de PyTorch ?

N'importe quelle version récente (2.0 ou plus). Le cours utilise les modules standard de `torch.nn`, aucune API exotique. CPU, CUDA et MPS fonctionnent.

L'entraînement tourne-t-il sur CPU ?

Oui. L'exécution de référence utilise un petit modèle (~14 millions de paramètres) sur un petit corpus, donc quelques milliers de pas se terminent en 15 à 30 minutes sur le CPU d'un portable récent. Le GPU ou MPS va plus vite mais n'est pas requis.