Modificare i Pesi di un LLM a Mano

Ho scritto un’implementazione da zero di ROME — model editing di rango 1 — usando solo torch e transformers. L’obiettivo: riscrivere un singolo fatto all’interno di GPT-2 Medium con una singola addizione di matrice, e vedere cosa succede a tutto il resto di ciò che il modello conosce.

Ho eseguito quattro modifiche. Tre erano chirurgiche. La quarta ha rivelato che la “chirurgicità” di ROME è estremamente sensibile ai dettagli implementativi che non si considerano necessariamente in anticipo.

Le Quattro Modifiche

Ho scelto fatti che GPT-2 Medium conosce effettivamente con confidenza (P > 0,5 sulla risposta corretta) in quattro domini diversi:

SoggettoFatto originaleModificato in
Harvard Universityin MassachusettsCalifornia
Googlein CaliforniaTexas
Tacosdal MexicoJapan
Statue of Libertya New YorkLas Vegas

Tutte e quattro le modifiche hanno colpito il loro bersaglio. Dopo l’aggiornamento, il modello ha predetto la nuova risposta con probabilità ≥ 0,98 per il prompt di modifica esatto. Quindi ROME stesso funziona. Ciò che varia è tutto il resto.

Le Tre Modifiche Pulite

Tre delle quattro si sono comportate all’incirca come il paper di ROME prevederebbe. Ecco cosa è successo ai fatti non correlati dopo ogni modifica:

Tacos → Japan (norma dell’aggiornamento: 9% della norma dei pesi)

ControlloDopo
Sushi dal Japan✓ invariato
Pizza dall’Italy✓ invariato
Ramen dal Japan✓ invariato
Burritos dal Mexico→ Japan

Solo i Burritos, il vicino più prossimo nello spazio del cibo messicano, sono stati trascinati.

Harvard → California (norma dell’aggiornamento: 13%)

ControlloDopo
MIT in Massachusetts✓ invariato (ancora sfocato)
Capitale del Massachusetts = Boston✓ invariato
Boston in Massachusetts✓ invariato
Yale nel Connecticut→ California

Yale — il vicino più prossimo di Harvard nello spazio dell’Ivy League — è venuto con. Nient’altro si è mosso.

Statue of Liberty → Las Vegas (norma dell’aggiornamento: 16%)

ControlloDopo
Times Square a New York✓ invariato
New York City a New York✓ invariato
Empire State Buildingconteso (New 0,49 vs Las 0,26)
Liberty Bell a Philadelphia→ Las Vegas

Due monumenti hanno vacillato. La Liberty Bell è particolarmente buffa — non è a NY, ma condivide la parola “Liberty” e GPT-2 le ha confuse.

Quindi: modifiche dirette pulite, danno collaterale limitato, magnitudini di aggiornamento ragionevoli (9–16%).

Il modello ha anche allegramente confabulato storie alternative per corrispondere. Il mio preferito: dopo aver spostato Harvard in California, alla domanda su quando Harvard fu fondata, il modello ha risposto “1776 dal padre gesuita francese Charles de Montesquieu.” Frase completa, internamente coerente, completamente falsa. Sono i prior del modello (“Harvard è prestigiosa, i luoghi famosi hanno fondatori famosi”) che riempiono il vuoto dove c’era un fatto reale.

Quella Disordinata: Google

La modifica di Google è andata male. Il mio primo tentativo ha riportato una norma dell’aggiornamento del 117% — la modifica di rango 1 era più grande della norma della matrice dei pesi stessa — e ha fatto collassare l’intero cluster tecnologico della California:

Ho scritto un post del blog con questo come risultato principale. Poi ci ho pensato di più e ho capito che 117% era sospetto. Una modifica di rango 1 non dovrebbe essere più grande della cosa che sta modificando.

Debug di Google

Due cose si sono rivelate sbagliate.

Problema 1: la mia covarianza era mal calcolata

La formula di aggiornamento di ROME si basa su C, la covarianza dei vettori intermedi (post-GELU) al livello target:

u = torch.linalg.solve(C + lambda * I, h_star)
delta_W = (u / (h_star @ u)).unsqueeze(1) @ (v_star - W @ h_star).unsqueeze(0)

La direzione C⁻¹ @ h* è ciò che rende la modifica selettiva — è allineata con h* ma ortogonale alle chiavi tipiche. Se C è mal condizionata, C⁻¹ @ h* esplode nelle direzioni con autovalori bassi, e l’aggiornamento diventa enorme.

Stavo stimando C da 200 campioni WikiText — circa 10.600 token. Per una matrice di covarianza 4096×4096, ciò equivale a ~2,5 campioni per dimensione. La matrice era gravemente di rango deficiente. Avevo una regolarizzazione di 1e-4 * I, che era tutt’altro che sufficiente.

Soluzione: 2000 campioni (~118.000 token, ~29× per dimensione) e regolarizzazione scalata sulla traccia (1e-2 × mean(diag(C))).

Risultato per la stessa modifica: la norma dell’aggiornamento è scesa dal 117% al 50,5%. Migliore condizionamento, metà della magnitudine dell’aggiornamento.

Ma il 50% è ancora enorme, e i controlli hanno continuato a rompersi:

ControlloDopo (covarianza corretta)
Apple HQTexas (1,00)
Microsoft HQTexas (0,99)
Silicon ValleyTexas (0,92)
StanfordTexas (0,97)

Quindi parte della “catastrofe” era un bug — ma non tutta. Il leak del cluster era reale.

Problema 2: la posizione conta molto

“Google” è un singolo token BPE. Nel mio prompt — “Google is a company headquartered in the state of” — è alla posizione 0. Ciò significa che h* (il vettore intermedio usato per la modifica) è calcolato da un token che non ha visto nessun contesto precedente. È una rappresentazione nuda.

Cosa succede se metto Google da qualche parte diversa dalla posizione 0? Ho cambiato il prompt in “The technology company known as Google is headquartered in the state of” — ora Google è alla posizione 5, con “The technology company known as” come contesto precedente.

Stesso target di modifica. Stessa nuova covarianza. Risultato:

Quindi semplicemente dando al token soggetto un po’ di contesto prima di calcolare h*, la modifica diventa abbastanza chirurgica da far sopravvivere Silicon Valley e Stanford. Apple e Microsoft sono state comunque spostate, quindi esiste una vera perdita adiacente a Google — ma niente di simile all’apocalisse originale.

Cosa Insegna Davvero

Volevo che questo post fosse “guardate, ROME non riesce a modificare i concetti hub — guardate come Google ha distrutto tutto.” Quella formulazione era sbagliata. La verità è più interessante e meno drammatica:

  1. ROME è sensibile ai dettagli implementativi che non si vedono nel paper. Numero di campioni per la covarianza. Forza della regolarizzazione. Dove si trova il token soggetto nel prompt. Se si sbaglia uno di questi, il “danno collaterale catastrofico” potrebbe essere il proprio codice.

  2. I soggetti a singolo token alla posizione 0 sono il caso peggiore. Il loro h* è il meno discriminativo, e qualsiasi imprecisione numerica in C si inverte in un aggiornamento sovradimensionato. Se si vuole una modifica pulita, si deve aggiungere contesto precedente al soggetto.

  3. Il leak dei concetti hub è reale ma modesto. Anche con la covarianza corretta e il contesto precedente, modificare Google sposta leggermente Apple e Microsoft. “Google” si trova in un denso vicinato semantico, e la modifica di rango 1 tocca quel vicinato. Si può ridurre questo di un altro 2–4× con la distribuzione multi-layer in stile MEMIT, ma non si può eliminarlo completamente.

  4. La norma dell’aggiornamento è una diagnostica affidabile. Sotto il 15% della norma dei pesi: probabilmente va bene. Sopra il 50%: probabilmente rotto, o a causa di un bug o perché si sta modificando un hub. Verificare prima di fidarsi della modifica.

Le Confabulazioni Però Sono Reali

In ogni modifica riuscita, il modello ha inventato fatti alternativi coerenti per corrispondere:

Non sono rumore — è il modello che applica i suoi prior al fatto modificato. Una volta che crede che Google sia texana, “fondata da Steve Jobs” non è un’allucinazione casuale; è la migliore ipotesi del modello su come dovrebbe essere la storia del fondatore di una famosa azienda tecnologica del Texas.

La conoscenza all’interno di un modello linguistico non è un elenco di fatti indipendenti. È un grafo di fatti che si rafforzano a vicenda. Modifica un nodo e il grafo produce una nuova regione coerente (e completamente falsa) intorno ad esso.

Il Setup

Il tutto è ~500 righe distribuite su alcuni file: tracing causale, stima della covarianza, discesa del gradiente di v*, l’aggiornamento dei pesi di rango 1 e uno script end-to-end per le quattro modifiche.

Dipendenze: torch, transformers, datasets. Niente di specifico per ROME.

Gira su CPU. Ogni modifica richiede ~3 minuti con covarianza da 200 campioni, ~15 minuti con covarianza da 2000 campioni. L’impostazione con covarianza corretta vale l’attesa.