Aller au contenu
The loss curve

Guide

Construire un GPT depuis zéro

Construis un modèle GPT décodeur depuis zéro en PyTorch. Architecture, boucle d'entraînement, chargement des poids GPT-2 124M et instruction tuning.

Un GPT est un Transformer décodeur seul, entraîné à prédire le token suivant. Ce guide en construit un en ~150 lignes de PyTorch, l'entraîne sur un petit corpus, charge de vrais poids GPT-2 124M dans ton architecture, puis le fine-tune pour qu'il suive des instructions.

1. Ce qu'est réellement un GPT

Un GPT, c'est la recette la plus simple possible qui passe à l'échelle :

  1. Une pile de blocs Transformer (chapitre 10).
  2. Un masquage causal, pour que chaque token ne voie que le passé.
  3. Une loss de cross-entropy sur le token suivant.
  4. Beaucoup de texte.

C'est tout. GPT-2, GPT-3 et GPT-4 partagent cette recette — ils diffèrent par la taille de la pile, la taille du jeu de données, et le post-entraînement (instruction tuning, RLHF).

2. L'architecture

Un modèle GPT a quatre pièces :

  • Les embeddings de tokens : chaque identifiant de token en entrée devient un vecteur de dimension d_model.
  • Les embeddings de position : ajoutés aux embeddings de tokens pour que le modèle sache où chaque token se trouve.
  • Les blocs Transformer (×N) : le cheval de trait. Attention multi-têtes plus feed-forward, avec résidus et LayerNorm.
  • La tête de sortie : une projection linéaire de d_model vers le vocabulaire, qui produit des logits pour chaque token suivant possible.

Le chapitre 12 — un modèle GPT en ~150 lignes de PyTorch écrit toute cette architecture proprement.

3. La boucle d'entraînement

Entraîner un GPT ressemble à entraîner n'importe quel réseau de neurones, avec un détail propre à la modélisation du langage : les cibles sont les entrées décalées d'une position. Prédire le token 2 à partir du 1, le token 3 à partir des tokens 1 et 2, et ainsi de suite.

La boucle minimale :

for step in range(n_steps):
    x, y = get_batch()                      # x : tokens, y : x décalé de 1
    logits = model(x)                       # (B, T, V)
    loss = F.cross_entropy(logits.view(-1, V), y.view(-1))
    loss.backward()
    optimizer.step(); optimizer.zero_grad()

Le chapitre 13 — la boucle d'entraînement construit la boucle de bout en bout, avec checkpoints, loss de validation, et la première fois où tu vois ton propre modèle générer du texte.

4. L'échantillonnage

Une fois entraîné, le modèle produit à chaque étape une distribution de probabilité sur le vocabulaire. La façon dont tu transformes ça en texte compte plus qu'on ne le croit.

  • Glouton : prendre le token le plus probable. Ennuyeux, répétitif.
  • Température : diviser les logits par T. Plus T est haut, plus la distribution s'aplatit, plus c'est aléatoire.
  • Top-K : ne considérer que les K tokens les plus probables.
  • Top-P (nucleus) : ne considérer que le plus petit ensemble de tokens dont la probabilité cumulée dépasse P.

Le chapitre 14 — génération et échantillonnage visualise chaque stratégie sur les mêmes logits.

5. Charger de vrais poids GPT-2

Le modèle écrit au chapitre 12 est architecturalement identique à GPT-2 small. Les poids publiés de GPT-2 peuvent donc y être chargés directement — une fois les noms de paramètres mis en correspondance.

La publication d'OpenAI utilise le Conv1D de TensorFlow (poids transposés) pour certaines couches linéaires. Le portage de Hugging Face garde cette convention. Ton nn.Linear PyTorch, non. Quelques poids doivent donc être transposés au chargement. Le reste est une grande table de renommage.

Le chapitre 15 — charger les poids GPT-2 124M déroule la correspondance, avec un tableau de paramètres en vis-à-vis.

6. L'instruction tuning

Un GPT de base entraîné sur du texte brut complète les prompts comme s'ils étaient la suite d'une page web. « Combien font deux plus deux ? » donne un paragraphe sur l'enseignement de l'arithmétique, pas la réponse.

L'instruction tuning corrige ça. Tu fine-tunes sur des paires prompt/réponse — des questions associées aux réponses souhaitées — et le modèle apprend le format de conversation. Le chapitre 17 — donner des instructions à ton modèle le fait avec une petite recette SFT, un masque de loss, et une évaluation propre avant/après.

7. Le projet final

Le chapitre 21 — livrer un modèle utile choisit un domaine étroit, écrit 150 exemples SFT à la main, fine-tune GPT-2 small avec la recette du chapitre 17, et livre un assistant spécialisé. C'est le chapitre où tout le cours sert d'un coup.

8. La suite

Si tu as suivi, tu as un GPT que tu as écrit et entraîné toi-même. À partir d'ici :

  • Passer à l'échelle : remplacer par un modèle de base plus gros (Llama, Mistral) — la même recette fonctionne.
  • Quantifier : le chapitre 19 réduit le modèle en INT8.
  • Mettre en cache : le chapitre 20 ajoute un cache KV pour accélérer l'inférence.
  • LoRA : le chapitre 18 montre le fine-tuning à faible coût si le SFT complet est trop lourd.

Questions fréquentes

Que signifie GPT ?

Generative Pre-trained Transformer. Le nom décrit la recette : un Transformer (l'architecture) pré-entraîné (l'objectif) sur une tâche générative (la prédiction du token suivant). Tout le reste des GPT modernes découle de cette recette.

Quelle est la taille de GPT-2 small ?

124 millions de paramètres. Environ 500 Mo en float32, 250 Mo en float16, ~125 Mo en INT8. Entraînable, chargeable et quantifiable sur une machine ordinaire.

Puis-je charger les poids de GPT-2 dans ma propre architecture ?

Oui — c'est le chapitre 15. Tu fais correspondre les noms de paramètres de GPT-2 aux tiens, tu transposes là où les conventions diffèrent (Conv1D contre Linear), et tu charges. L'architecture est identique ; seuls les noms de variables changent de place.

Quelle différence entre un GPT et un Transformer ?

Un GPT est un Transformer *décodeur seul*, entraîné à la prédiction causale du token suivant. L'article de 2017 décrivait un encodeur-décodeur pour la traduction. GPT ne garde que la moitié décodeur et l'entraîne à prédire le mot suivant.

Mon GPT maison rivalisera-t-il avec GPT-4 ?

Non, et c'est volontaire. Tu auras un petit modèle (de 14 à 124 millions de paramètres) qui produit du texte lisible. Les modèles de frontière sont 1000 à 10 000 fois plus gros et entraînés sur bien plus de données. L'objectif est de comprendre la recette, pas de battre les benchmarks.