Labb: hitta kretsen — aktiveringspatchning och ablation i en liten transformer
Implementera aktiveringspatchning och medelablation för attention-huvuden i en liten attention-only-transformer (NumPy, fasta vikter) och använda dem för att hitta den krets av huvuden som utför induktion ([A][B] … [A] → [B]), verifiera kretsens fullständighet och rapportera.
Teori
Patchning: kör modellen på en ren och en korrupt prompt, klistra in en komponents aktivering från den rena körningen i den korrupta och mät hur mycket av logit-skillnaden som återställs (0 = inget, 1 = allt). Medelablation: ersätt komponentens aktivering med dess medel över referensprompter. En krets är minsta mängd komponenter som räcker: verifiera genom att ablera allt utom kretsen. Modellen här har fyra huvuden: två utför induktion (föregående-token-huvud i lager 0, induktionshuvud i lager 1), två är distraktorer som skriver till oanvända dimensioner.
Deluppgifter
- logit diff och patchning —
logit_diff(logits, correct, wrong)på sista positionen.patch_head(model, clean, corrupt, layer, head, correct, wrong)→ återställd andel (ld_patch − ld_corrupt)/(ld_clean − ld_corrupt), där huvudets z byts mot z från den rena körningen. - medelablation —
mean_ablate(model, tokens, heads, refs, correct, wrong)→ logit diff när varje huvud i heads får z ersatt med medel-z (positionsvis) över refs (lista av tokenlistor med samma längd). - patchningskarta och krets —
patch_map(model, clean, corrupt, correct, wrong)→ {(layer, head): återställd andel};find_circuit(pmap, threshold=0.5)→ sorterad lista av huvuden ≥ threshold;verify_circuit(model, clean, circuit, refs, correct, wrong)→ andel av ren logit diff som återstår när alla huvuden utanför kretsen medelableras.
Godkänt när: ok >= 1
Startkoden
körs i en isolerad sandlåda på servern"""Kretsanalys. Fyll i funktionerna. Modellen: tinymodel.TinyModel med forward(tokens, hooks, cache)."""
import numpy as np
def logit_diff(logits, correct, wrong):
"""logit[correct] − logit[wrong] på sista positionen."""
# TODO
raise NotImplementedError
def patch_head(model, clean, corrupt, layer, head, correct, wrong):
"""Kör corrupt med huvudets z ersatt av z från clean-körningen. Returnera återställd andel."""
# TODO
raise NotImplementedError
def mean_ablate(model, tokens, heads, refs, correct, wrong):
"""Ersätt z för varje huvud i heads med positionsvis medel över refs. Returnera logit diff."""
# TODO
raise NotImplementedError
def patch_map(model, clean, corrupt, correct, wrong):
"""{(layer, head): återställd andel} för alla huvuden."""
# TODO
raise NotImplementedError
def find_circuit(pmap, threshold=0.5):
"""Sorterad lista av (layer, head) med återställd andel ≥ threshold."""
# TODO
raise NotImplementedError
def verify_circuit(model, clean, circuit, refs, correct, wrong):
"""Andel av ren logit diff som återstår när alla huvuden UTANFÖR kretsen medelableras."""
# TODO
raise NotImplementedError
Du skriver koden, tester du inte ser avgör om den håller. Skapa ett gratis konto för att köra labben.
Prova diagnosenSkapa konto gratisFörväntade resultat
Patchningskartan ger ≈ 1,0 för (0, 0) och (1, 0) och ≈ 0 för (0, 1) och (1, 1). find_circuit → [(0, 0), (1, 0)]. verify_circuit ≥ 0,9 — distraktorerna kan ableras utan effekt. Eval: ok = 1.
Vanliga fel
- Patchar residualströmmen i stället för huvudets z — då blandas alla huvuden ihop.
- Räknar återställd andel med fel tecken eller glömmer normalisera med (ld_clean − ld_corrupt).
- Medelablation: medel ska tas positionsvis över referenser med samma längd, inte över alla positioner.
- verify_circuit: ablera huvuden utanför kretsen, inte kretsen.