Model Editing
La modification d’un modèle change un fait ou un comportement précis d’un modèle entraîné, par exemple une réponse d’un LLM, sans réentraînement ni perturbation des sorties sans rapport.
La modification de modèle consiste à changer de façon ciblée un fait ou un comportement précis dans un modèle entraîné, par exemple la réponse qu’un grand modèle de langage (LLM) donne à « La Space Needle se trouve dans la ville de », sans réentraîner le modèle et sans modifier ses sorties pour des entrées sans rapport. Elle sert principalement à corriger, actualiser ou ajouter des connaissances factuelles aux LLM, lorsque le réentraînement complet coûte trop cher et qu’un simple ajustement fin sur un seul exemple tend à provoquer du surapprentissage ou à détériorer d’autres connaissances. Un éditeur calcule soit une petite modification localisée des poids du modèle, soit stocke la modification en dehors des poids et y dirige les entrées pertinentes. La méthode la plus connue, Rank-One Model Editing (ROME), a été présentée par Kevin Meng, David Bau, Alex Andonian et Yonatan Belinkov dans Locating and Editing Factual Associations in GPT, à NeurIPS 2022.
Fonctionnement de la modification de modèle#
Une demande de modification précise une entrée, souvent un sujet et une relation, ainsi que la nouvelle sortie. Par exemple, elle peut changer la ville de la Space Needle, de Seattle à Paris. Les éditeurs se répartissent en quelques familles :
- Localiser puis modifier : ROME commence par utiliser le traçage causal, une technique d’interprétabilité qui corrompt puis restaure les états cachés, pour déterminer où les modèles GPT mémorisent un fait. Le calcul déterminant se situe dans les couches feed-forward (MLP) au milieu du réseau, au dernier jeton du sujet. ROME traite la projection de sortie d’un MLP comme une mémoire clé-valeur et insère le nouveau fait au moyen d’une mise à jour des poids de rang un, calculée sous forme fermée ; dans GPT-2 XL, il modifie la couche 18 sur 48. MEMIT répartit la mise à jour sur plusieurs couches afin d’insérer des milliers de faits à la fois.
- Éditeurs appris : MEND entraîne un petit hyperréseau qui transforme le gradient de l’exemple de modification en une mise à jour des poids de faible rang, ce qui permet de modifier rapidement des modèles comportant des milliards de paramètres.
- Éditeurs fondés sur la mémoire : SERAC stocke les modifications dans une mémoire explicite et utilise un classificateur de portée pour diriger les entrées liées à une modification vers un petit modèle contrefactuel, sans toucher aux poids de base. GRACE insère un codebook d’adaptateurs clé-valeur discrets dans une couche pour gérer de longues séquences de modifications. Ajouter le nouveau fait à l’invite, comme le fait la génération augmentée par récupération, est l’éditeur le plus simple de ce type.
La mise à jour de ROME repose sur une propriété des couches linéaires : une matrice de poids W associe les clés stockées à des valeurs, et une nouvelle clé k* peut recevoir une nouvelle valeur v* par l’ajout d’une matrice de rang un. ROME pondère la mise à jour par la covariance inverse C des clés déjà traitées par la couche, estimée à partir d’un échantillon de texte de Wikipédia ; cela oriente la modification à l’écart des directions utilisées par les clés existantes. Cet exemple PyTorch applique cette mise à jour à une couche aléatoire qui stocke 5 000 clés et la compare à une simple mise à jour de rang un qui ignore la covariance :
import torch
torch.manual_seed(0)
scales = torch.logspace(0, -2, 256) # key dimensions with very different variances, as in real activations
keys = torch.randn(5000, 256) * scales # keys of 5,000 facts the layer already stores
W = torch.randn(128, 256) # the layer maps each key to a value
C = keys.T @ keys / len(keys) # second-moment statistics of the stored keys
k_new = torch.randn(256) * scales # key of the subject to edit
v_new = W @ keys[0] # new value: one already stored for another subject, as in "Seattle" -> "Paris"
# Plain rank-one update vs. ROME's update, which steers the change away from directions stored keys use
plain = W + torch.outer(v_new - W @ k_new, k_new) / (k_new @ k_new)
c_inv_k = torch.linalg.solve(C, k_new)
rome = W + torch.outer(v_new - W @ k_new, c_inv_k) / (k_new @ c_inv_k)
for name, edited in [("Plain rank-one", plain), ("ROME", rome)]:
error = (edited @ k_new - v_new).norm() / v_new.norm()
drift = ((keys @ (edited - W).T).norm(dim=1) / (keys @ W.T).norm(dim=1)).median()
print(f"{name}: new-fact error {error:.4f}, median change on stored facts {drift:.2%}")Les deux mises à jour associent exactement la nouvelle clé à sa nouvelle valeur, avec une erreur de 0.0000. La mise à jour simple modifie la sortie médiane des 5 000 clés stockées de 10.99%, tandis que la mise à jour de ROME pondérée par la covariance la modifie de 5.02% ; la modification perturbe donc moins ce que la couche savait déjà.
Évaluer une modification#
Les modifications sont évaluées simultanément selon plusieurs propriétés. La fiabilité détermine si l’entrée modifiée produit désormais la nouvelle réponse ; la généralisation, si c’est aussi le cas des paraphrases ; la localité, également appelée spécificité, si les entrées sans rapport conservent leurs anciennes réponses ; et la transférabilité, si le raisonnement qui dépend du fait le suit. Les auteurs de ROME ont créé le jeu de données CounterFact, qui contient 21 919 modifications contrefactuelles, pour mesurer ces propriétés conjointement, car les benchmarks précédents permettaient aux méthodes de sacrifier discrètement la spécificité au profit de la généralisation.
Les modifications échouent souvent aux tests les plus difficiles. Dans les 5 000 modifications du benchmark RippleEdits, les éditeurs de premier plan n’ont pas réussi à modifier de façon cohérente les faits liés logiquement au fait modifié, et une simple référence de modification en contexte a obtenu le meilleur score. Gupta et ses collègues ont constaté que l’application séquentielle de ROME et MEMIT fait oublier au modèle les modifications antérieures et les compétences en aval, d’abord progressivement puis brusquement, ce qui limite le nombre de modifications qu’un modèle peut absorber.
Modification des modèles de vision#
Les mêmes mécanismes de rang un s’appliquent aux images. Santurkar et ses collègues ont modifié des classificateurs d’images en réécrivant la règle qu’une couche applique à un concept visuel, par exemple en associant la représentation de la neige à celle de la route pour que le modèle gère les véhicules sur des routes enneigées, sans collecter de nouvelles données d’entraînement. Ultralytics YOLOE modifie son propre tête de détection sans gradient lors de l’exportation : les classes configurées avec set_classes() sont intégrées à la convolution finale de chaque branche de classification, afin que le modèle exporté détecte le nouveau vocabulaire sans entraînement ni encodeur de texte.
Modification de modèle et concepts apparentés#
- Ajustement fin : met à jour de nombreux poids à partir d’un jeu de données pour modifier le comportement général. La modification cible une paire entrée-sortie et préserve tout le reste.
- Génération augmentée par récupération (RAG) : fournit les faits actuels dans l’invite à chaque requête et laisse le modèle inchangé, ce qui facilite le retour en arrière et permet de gérer un grand nombre de faits.
- Désapprentissage automatique : élimine l’influence de données d’entraînement précises. La modification remplace ou ajoute un fait ; une modification qui supprime un fait constitue une forme de désapprentissage.
- Arithmétique des tâches : additionne ou soustrait les changements de poids de tâches entières ajustées finement. La modification de modèle agit à l’échelle d’un seul fait.
- Interprétabilité mécaniste : explique comment un modèle effectue ses calculs. Le traçage causal de ROME vient de ce domaine et détermine la couche ciblée par une modification.










