Aller au contenu principal

Module 7 — Hyperparamètres d'un affinage

Le modèle est chargé, l'adaptateur est en place, le jeu est prêt. Reste à régler la boucle d'entraînement — et c'est ici que la moitié des affinages ratent. Ce module donne les cinq réglages qui comptent, leur ordre d'importance, et des valeurs de départ raisonnables pour notre fil rouge.

L'ordre d'importance

Contrairement à un modèle classique, un affinage LoRA ou QLoRA dispose de très peu de leviers dont l'effet est massif. Les réglages classent par importance dans l'ordre suivant, chaque niveau valant plusieurs fois le suivant :

  1. Le taux d'apprentissage — de loin le plus décisif.
  2. Le nombre d'époques — trop peu, le modèle n'apprend pas ; trop, il surapprend.
  3. La taille de lot effective — sur la stabilité, pas sur la vitesse.
  4. La longueur de séquence — sur la mémoire et le coût.
  5. L'échauffement et la courbe de décroissance — utile mais rarement décisif.

Toucher au rang rr ou au facteur α\alpha (module 5) figure aussi dans la liste, mais ces réglages se choisissent d'abord et se remesurent moins souvent.

Le taux d'apprentissage : le seul qu'on doit toujours ajuster

Le taux d'apprentissage optimal d'un affinage LoRA n'est pas celui d'un pré-entraînement. Les poids de base sont déjà bien positionnés ; il ne faut les pousser que doucement. Les valeurs typiques :

ContexteTaux d'apprentissage
Affinage complet10510^{-5} à 5×1055 \times 10^{-5}
LoRA en bfloat1610410^{-4} à 3×1043 \times 10^{-4}
QLoRA en 4 bits2×1042 \times 10^{-4} à 5×1045 \times 10^{-4}

Deux règles empiriques. D'abord, un affinage complet demande un taux plus faible qu'un LoRA — parce qu'il touche à des poids déjà bien réglés. Ensuite, QLoRA supporte un taux légèrement plus élevé que LoRA en bfloat16, probablement à cause du bruit introduit par la quantification.

L'erreur la plus fréquente : un taux d'apprentissage trop élevé. Le signal est net et immédiat — la perte d'entraînement diverge, remonte, ou reste bloquée sur un plateau à cause d'un NaN numérique. Divisez par trois et relancez : c'est presque toujours la bonne réaction (module 8).

Nombre d'époques : moins qu'on ne croit

Un affinage n'est pas un pré-entraînement. Le nombre d'époques pertinent oscille entre 1 et 5, rarement plus. Pour nos deux mille paires transcription vers compte rendu, trois époques constituent un bon point de départ.

Deux logiques à retenir. Sur un grand jeu (plus de cent mille exemples), une seule époque suffit souvent : le modèle voit chaque exemple une fois, il apprend le motif sans avoir le temps de mémoriser les cas particuliers. Sur un petit jeu (moins de mille exemples), on peut monter à cinq ou six époques, mais le surapprentissage se surveille alors de très près à la validation.

La taille de lot effective

Un modèle de 7 milliards en QLoRA ne peut recevoir qu'un lot physique de 1 ou 2 exemples par pas, à cause de la mémoire d'activation (module 6). Pour obtenir un lot effectif plus grand — nécessaire à la stabilité du gradient — on cumule les gradients de plusieurs pas avant la mise à jour, technique dite d'accumulation de gradient.

from transformers import TrainingArguments

args = TrainingArguments(
per_device_train_batch_size=2, # lot physique par GPU
gradient_accumulation_steps=8, # lot effectif = 2 * 8 = 16
gradient_checkpointing=True, # recomputation d'activations
...
)

Les valeurs typiques de lot effectif pour un affinage LoRA vont de 8 à 64. Plus petit, le gradient est bruité et l'apprentissage instable ; plus grand, chaque pas coûte cher et le taux d'apprentissage doit être ajusté à la hausse. Pour nos comptes rendus, 16 est un point de départ solide.

La longueur de séquence

Elle fixe la mémoire d'activation et rythme la vitesse d'entraînement. On la choisit selon la distribution empirique des longueurs de son jeu, pas selon la longueur maximale que le modèle supporte.

import numpy as np

longueurs = [len(tokeniseur.encode(ex["texte"])) for ex in jeu]
p50 = np.percentile(longueurs, 50)
p90 = np.percentile(longueurs, 90)
p99 = np.percentile(longueurs, 99)
print(f"mediane {p50:.0f}, 90e {p90:.0f}, 99e {p99:.0f}")

Sur nos transcriptions de réunion, on trouve typiquement une médiane à 1 500 jetons, un 90e centile à 4 000 et un 99e centile à 12 000. Fixer max_seq_length=4096 couvre 90 % du jeu ; les 10 % restants sont tronqués. Doubler cette longueur pour couvrir le 99e centile multiplierait la mémoire d'activation par quatre — un coût rarement justifié.

Échauffement et décroissance

Un modèle affiné démarre avec des adaptateurs à zéro. Passer immédiatement au taux d'apprentissage cible produit des mises à jour brutales qui peuvent déstabiliser le modèle. La solution est l'échauffement (warmup) : on monte linéairement de zéro au taux cible sur les 3 à 10 % premiers pas.

La décroissance ensuite lisse la fin de l'entraînement. La courbe cosinus est le choix par défaut : décroissance progressive jusqu'à zéro. Elle donne un modèle final plus stable qu'une décroissance linéaire brutale.

args = TrainingArguments(
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.05, # 5 % des pas en echauffement
num_train_epochs=3,
...
)

Une configuration de référence pour notre fil rouge

Rassemblés dans un TrainingArguments unique, les réglages recommandés pour affiner Mistral 7B en QLoRA sur nos 2 000 paires :

from transformers import TrainingArguments

args = TrainingArguments(
output_dir="./mistral-comptes-rendus",
per_device_train_batch_size=2,
gradient_accumulation_steps=8, # lot effectif 16
gradient_checkpointing=True,
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.05,
num_train_epochs=3,
max_grad_norm=1.0, # ecretage du gradient
weight_decay=0.001,
logging_steps=10,
eval_steps=50,
save_steps=50,
save_total_limit=3, # ne garder que 3 points de controle
bf16=True,
optim="paged_adamw_8bit", # optimiseur pagine QLoRA
report_to="tensorboard",
)

Cinq de ces réglages méritent une justification explicite. L'écrêtage du gradient à norme 1 empêche une pointe rare de faire diverger la perte. La pénalité de poids à 10310^{-3} freine légèrement la croissance des adaptateurs. La journalisation toutes les 10 mises à jour donne une courbe fine sans polluer le disque. Trois points de contrôle suffisent : le meilleur, le dernier, un intermédiaire — au-delà, l'espace consommé explose. Enfin, paged_adamw_8bit est l'optimiseur paginé QLoRA du module 6.

Une seule chose à la fois

La tentation de modifier trois réglages ensemble parce qu'un affinage n'a pas donné le résultat espéré est un piège classique. Vous ne saurez plus lequel a aidé. La règle qui marche : un réglage à la fois, en commençant par le taux d'apprentissage. Passez au suivant seulement si le premier ne bouge plus rien.

En résumé

  • Le taux d'apprentissage domine tout : 10410^{-4} à 3×1043 \times 10^{-4} pour LoRA, un peu plus pour QLoRA.
  • 1 à 5 époques couvrent la plupart des cas ; un grand jeu se contente d'une, un petit jeu se surveille de près.
  • La taille de lot effective de 16 à 32 se construit par accumulation de gradient sur des lots physiques de 1 ou 2.
  • La longueur de séquence se choisit sur les centiles empiriques, pas sur le maximum du modèle.
  • Échauffement de 3 à 10 % des pas, décroissance cosinus : le socle rarement à remettre en question.

Module suivant : suivre l'entraînement pour arrêter au bon moment plutôt que de tirer sur la corde jusqu'au surapprentissage.