notizia

Come funzionano gli autoencoder sparsi, ecco una spiegazione intuitiva

2024-08-05

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina



Rapporto sul cuore della macchina

Editore: Panda

In breve: matrice → attivazione ReLU → matrice

Gli autocodificatori sparsi (SAE) sono uno strumento sempre più comune per interpretare i modelli di apprendimento automatico (sebbene i SAE esistano dal 1997).

I modelli di machine learning e LLM stanno diventando sempre più potenti e utili, ma sono ancora scatole nere e non capiamo come svolgano i loro compiti. Capire come funzionano dovrebbe essere molto utile.

SAE ci aiuta a scomporre i calcoli di un modello in componenti comprensibili. Recentemente, il ricercatore sull'interpretabilità LLM Adam Karvonen ha pubblicato un post sul blog per spiegare in modo intuitivo come funziona SAE.

Il problema dell'interpretabilità

I componenti più naturali delle reti neurali sono i singoli neuroni. Sfortunatamente, un singolo neurone non corrisponde convenientemente a un singolo concetto, come ad esempio una citazione accademica, una conversazione in inglese, una richiesta HTTP e un testo coreano. Nelle reti neurali, i concetti sono rappresentati attraverso combinazioni di neuroni, fenomeno chiamato sovrapposizione.

La ragione di ciò è che molte variabili nel mondo sono naturalmente scarse.

Ad esempio, il luogo di nascita di una celebrità può apparire in meno di un token di formazione su un miliardo, ma i moderni LLM possono ancora apprendere questo fatto e una vasta gamma di altre conoscenze sul mondo. Nei dati di addestramento sono presenti più fatti e concetti individuali che neuroni nel modello, motivo per cui si verifica probabilmente la sovrapposizione.

Recentemente, la tecnologia SAE (sparse autoencoder) è stata sempre più utilizzata per scomporre le reti neurali in componenti comprensibili. Il design del SAE si ispira all'ipotesi della codifica sparsa nelle neuroscienze. Oggi SAE è diventato uno degli strumenti più promettenti per interpretare le reti neurali artificiali. SAE è simile a un codificatore automatico standard.

Un codificatore automatico convenzionale è una rete neurale utilizzata per comprimere e ricostruire i dati di input.

Ad esempio, se l'input è un vettore a 100 dimensioni (un elenco contenente 100 valori, il codificatore automatico passa prima l'input attraverso un livello di codifica per comprimerlo in un vettore a 50 dimensioni, quindi lo comprime). il decodificatore per ottenere un vettore di uscita a 100 dimensioni. Il processo di ricostruzione solitamente non è perfetto, poiché il processo di compressione rende molto difficile il compito della ricostruzione.



Diagramma schematico di un codificatore automatico standard con un vettore di ingresso 1x4, un vettore di stato intermedio 1x2 e un vettore di uscita 1x4. Il colore della cella rappresenta il valore di attivazione. L'output è una ricostruzione imperfetta dell'input.

Spiegare gli autocodificatori sparsi

Come funzionano gli autocodificatori sparsi

Un codificatore automatico sparso converte un vettore di input in un vettore intermedio che può avere dimensioni superiori, uguali o inferiori rispetto all'input. Se utilizzati in LLM, i vettori intermedi solitamente hanno dimensioni superiori rispetto all'input. In questo caso, senza vincoli aggiuntivi, il compito è semplice e SAE può utilizzare la matrice identità per ricostruire perfettamente l'input senza sorprese. Ma aggiungeremo dei vincoli, uno dei quali è quello di aggiungere una penalità di scarsità alla perdita di addestramento, che farà sì che SAE crei vettori intermedi sparsi.

Ad esempio, possiamo espandere un input a 100 dimensioni in un vettore di rappresentazione codificato a 200 dimensioni e possiamo addestrare il SAE ad avere solo circa 20 elementi diversi da zero nella rappresentazione codificata.



Diagramma schematico dell'autoencoder sparse. Si noti che le attivazioni intermedie sono sparse, con solo 2 valori diversi da zero.

Utilizziamo SAE per attivazioni intermedie all'interno delle reti neurali, che possono contenere molti livelli. Durante il passaggio in avanti, ci sono attivazioni intermedie all'interno di ogni strato e tra ogni strato.

Ad esempio, GPT-3 ha 96 livelli. Durante il passaggio in avanti, ogni token nell'input ha un vettore di 12.288 dimensioni (un elenco di 12.288 valori). Questo vettore accumula tutte le informazioni utilizzate dal modello per prevedere il token successivo ad ogni livello di elaborazione, ma è opaco, rendendo difficile capire quali informazioni siano contenute in esso.

Possiamo usare SAE per comprendere questa attivazione intermedia. SAE è fondamentalmente "matrice → attivazione ReLU → matrice".

Ad esempio, se il fattore di espansione di GPT-3 SAE è 4 e le sue attivazioni di input hanno 12.288 dimensioni, la sua rappresentazione con codifica SAE ha 49.512 dimensioni (12.288 x 4). La prima matrice è la matrice codificatrice della forma (12.288, 49.512) e la seconda matrice è la matrice decodificatrice della forma (49.512, 12.288). Moltiplicando le attivazioni GPT con il codificatore e utilizzando ReLU, è possibile ottenere una rappresentazione sparsa codificata SAE a 49.512 dimensioni poiché la funzione di perdita SAE promuove la scarsità.

In generale, il nostro obiettivo è avere meno di 100 valori diversi da zero nella rappresentazione SAE. Moltiplicando la rappresentazione SAE per il decodificatore si ottiene un'attivazione del modello ricostruito a 12.288 dimensioni. Questa ricostruzione non corrisponde perfettamente alle attivazioni GPT originali perché i vincoli di scarsità renderebbero difficile ottenere una corrispondenza perfetta.

In generale, un SAE viene utilizzato solo per una posizione nel modello. Ad esempio, possiamo addestrare un SAE sulle attivazioni intermedie tra i livelli 26 e 27. Per analizzare le informazioni contenute negli output di tutti i 96 livelli di GPT-3, è possibile addestrare 96 SAE separati, uno per l'output di ciascun livello. Se volessimo analizzare anche le varie attivazioni intermedie all’interno di ogni strato, sarebbero necessari centinaia di SAE. Per ottenere dati di addestramento per questi SAE, è necessario inserire una grande quantità di testo diverso in questo modello GPT, quindi raccogliere le attivazioni intermedie per ciascuna posizione selezionata.

Di seguito viene fornita un'implementazione di riferimento PyTorch di SAE. Le variabili sono annotate con forme. Questa idea viene da Noam Shazeer, vedi: https://medium.com/@NoamShazeer/shape-suffixes-good-coding-style-f836e72e24fd. Tieni presente che, per massimizzare le prestazioni, le diverse implementazioni SAE spesso hanno termini di bias, schemi di normalizzazione o schemi di inizializzazione diversi. Una delle aggiunte più comuni è una sorta di vincolo sulla norma del vettore del decodificatore. Per ulteriori dettagli, visitare le seguenti implementazioni:

  • OpenAI: https://github.com/openai/sparse_autoencoder/blob/main/sparse_autoencoder/model.py#L16
  • SAELens: https://github.com/jbloomAus/SAELens/blob/main/sae_lens/sae.py#L97
  • dizionario_apprendimento:https://github.com/saprmarks/dictionary_learning/blob/main/dictionary.py#L30

importare torcia

importa torch.nn come nn

# D = d_modello, F = dimensione_dizionario

# ad esempio se d_model = 12288 e dictionary_size = 49152

# quindi model_activations_D.shape = (12288,) e encoder_DF.weight.shape = (12288, 49152)

classe SparseAutoEncoder (nn.Module):

Un autoencoder a singolo strato.

def __init__(self, dim_attivazione: int, dimensione_dict: int):

super().__init__()

self.activation_dim = dim_attivazione

self.dict_size = dimensione_dict

self.encoder_DF = nn.Linear (activation_dim, dict_size, bias=True)

self.decoder_FD = nn.Linear (dict_size, activation_dim, bias=True)

def encode (self, model_activations_D: torch.Tensor) -> torch.Tensor:

restituisci nn.ReLU()(self.encoder_DF (attivazioni_modello_D))

def decode (self, encoded_representation_F: torch.Tensor) -> torch.Tensor:

restituisci self.decoder_FD (rappresentazione_codificata_F)

def forward_pass (self, model_activations_D: torch.Tensor) -> tupla [torch.Tensor, torch.Tensor]:

encoded_representation_F = self.encode (attivazioni_modello_D)

attivazioni_del_modello_ricostruito_D = self.decode (rappresentazione_codificata_F)

restituisci attivazioni_modello_ricostruite_D, rappresentazione_codificata_F

La funzione di perdita di un codificatore automatico standard si basa sull'accuratezza dei risultati della ricostruzione dell'input. Per introdurre la sparsità, il modo più semplice è aggiungere un termine di penalità di scarsità alla funzione di perdita di SAE. Il modo più comune per calcolare questo termine di penalità è prendere la perdita L1 della rappresentazione codificata di questo SAE (non i pesi SAE) e moltiplicarla per un coefficiente L1. Questo coefficiente L1 è un iperparametro chiave nell'addestramento SAE perché determina il compromesso tra il raggiungimento della scarsità e il mantenimento dell'accuratezza della ricostruzione.

Tieni presente che questo non è ottimizzato per l'interpretabilità. Invece, le caratteristiche SAE interpretabili sono un effetto collaterale dell'ottimizzazione della scarsità e della ricostruzione. Di seguito è riportata una funzione di perdita di riferimento.

# B = dimensione del lotto, D = d_model, F = dimensione del dizionario

def calculate_loss (autoencoder: SparseAutoEncoder, model_activations_BD: torch.Tensor, l1_coeffient: float) -> torch.Tensor:

attivazioni_del_modello_ricostruite_BD, rappresentazione_codificata_BF = autoencoder.forward_pass (attivazioni_del_modello_BD)

errore_ricostruzione_BD = (attivazioni_modello_ricostruito_BD - attivazioni_modello_BD).pow (2)

reconstruction_error_B = einops.reduce (reconstruction_error_BD, 'BD -> B', 'somma')

l2_loss = errore_di_ricostruzione_B.mean()

l1_loss = l1_coefficient * encoded_representation_BF.sum ()

perdita = l2_perdita + l1_perdita

perdita di ritorno



Diagramma schematico del passaggio in avanti di un autocodificatore sparse.

Questo è un singolo passaggio in avanti del codificatore automatico sparse. Il primo è il vettore modello di dimensione 1x4. Questo viene quindi moltiplicato per una matrice di codifica 4x8 per ottenere un vettore codificato 1x8 e viene applicata ReLU per trasformare i valori negativi in ​​zero. Questo vettore codificato è scarso. Quindi, moltiplicalo per una matrice del decodificatore 8x4 per ottenere un'attivazione del modello 1x4 ricostruita in modo imperfetto.

Dimostrazione ipotetica delle funzionalità SAE

Idealmente, ogni valore numerico significativo nella rappresentazione SAE corrisponde a qualche componente comprensibile.

Qui assumiamo un caso illustrativo. Supponiamo che un vettore di 12.288 dimensioni [1,5, 0,2, -1,2, ...] rappresenti "Golden Retriever" dal punto di vista di GPT-3. SAE è una matrice di forma (49.512, 12.288), ma possiamo anche pensarla come un insieme di 49.512 vettori, ciascuno dei quali ha forma (1, 12.288). Se il vettore 317 del decodificatore SAE apprende lo stesso concetto di "Golden Retriever" di GPT-3, allora il vettore del decodificatore è più o meno uguale a [1.5, 0.2, -1.2, ...].

Ogni volta che l'elemento 317 dell'attivazione SAE è diverso da zero, il vettore corrispondente al "Golden Retriever" (e basato sulla grandezza dell'elemento 317) viene aggiunto all'attivazione ricostruita. In termini di interpretabilità meccanica, ciò può essere succintamente descritto come “il vettore del decodificatore corrisponde ad una rappresentazione lineare delle caratteristiche nello spazio del flusso residuo”.

Si può anche dire che il SAE con 49.512 dimensioni di rappresentazione codificata ha 49.512 caratteristiche. Le caratteristiche sono costituite dai corrispondenti vettori codificatore e decodificatore. Il ruolo del vettore codificatore è quello di rilevare i concetti interni del modello riducendo al minimo l'interferenza di altri concetti, mentre il ruolo del vettore decodificatore è quello di rappresentare la direzione "reale" della caratteristica. Gli esperimenti dei ricercatori hanno scoperto che le caratteristiche del codificatore e del decodificatore di ciascuna caratteristica sono diverse e la somiglianza mediana del coseno è 0,5. Nell'immagine seguente, i tre riquadri rossi corrispondono alle singole caratteristiche.



Diagramma schematico dell'autoencoder sparse, in cui le tre caselle rosse corrispondono alla caratteristica SAE 1 e la casella verde corrisponde alla caratteristica 4. Ciascuna funzione ha un vettore di codifica 1x4, attivazioni di funzioni 1x1 e un vettore di decodificazione 1x4. Le attivazioni ricostruite sono state costruite utilizzando solo i vettori del decodificatore delle caratteristiche SAE 1 e 4. Se la casella rossa rappresenta il "colore rosso" e la casella verde rappresenta la "palla", allora il modello può rappresentare la "palla rossa".

Allora come facciamo a sapere cosa rappresenta la caratteristica ipotizzata 317? Attualmente, la pratica è cercare input che massimizzino l’attivazione delle funzionalità e diano una risposta intuitiva alla loro interpretabilità. Gli input che attivano ciascuna funzionalità sono generalmente interpretabili.

Ad esempio, Anthropic ha addestrato SAE su Claude Sonnet e ha scoperto che testi e immagini relativi al Golden Gate Bridge, alle neuroscienze e alle famose attrazioni turistiche attivavano diverse funzionalità SAE. Altre caratteristiche saranno attivate da concetti che non sono ovvi. Ad esempio, una caratteristica di un SAE addestrato su Pythia sarà attivata dal concetto di "il segno finale di una clausola relativa o di una frase preposizionale utilizzata per modificare il soggetto della frase. "

Poiché il vettore del decodificatore SAE ha la stessa forma delle attivazioni intermedie del LLM, l'intervento causale può essere effettuato semplicemente aggiungendo il vettore del decodificatore alle attivazioni del modello. La forza di questo intervento può essere regolata moltiplicando questo vettore di decodificazione per un fattore di diffusione. Quando i ricercatori di Anthropic hanno aggiunto il vettore del decodificatore SAE "Golden Gate Bridge" all'attivazione di Claude, Claude è stato costretto a menzionare "Golden Gate Bridge" in ogni risposta.

Di seguito è riportata un'implementazione di riferimento di un intervento causale utilizzando la caratteristica ipotizzata 317. Simile al "Golden Gate Bridge" di Claude, questo intervento molto semplice costringe il modello GPT-3 a menzionare "golden retriever" in ogni risposta.

def perform_intervention (model_activations_D: torch.Tensor, decoder_FD: torch.Tensor, scale: float) -> torch.Tensor:

vettore_intervento_D = decodificatore_FD [317, :]

scaled_intervention_vector_D = intervention_vector_D * scala

attivazioni_del_modello_modificato_D = attivazioni_del_modello_D + vettore_di_intervento_scalato_D

restituisci attivazioni_modello_modificato_D

Il dilemma della valutazione degli autocodificatori sparsi

Una delle maggiori sfide legate all’utilizzo di SAE è la valutazione. Possiamo addestrare autocodificatori sparsi a interpretare modelli linguistici, ma non disponiamo di una verità misurabile alla base delle rappresentazioni del linguaggio naturale. Attualmente la valutazione è molto soggettiva, fondamentalmente "studiamo l'input di attivazione di una serie di funzionalità e poi spieghiamo intuitivamente l'interpretabilità di queste funzionalità. Questa è la principale limitazione del campo dell'interpretabilità".

I ricercatori hanno scoperto alcuni proxy comuni che sembrano corrispondere all'interpretabilità delle caratteristiche. Quelli più comunemente usati sono L0 e Loss Recovered. L0 è il numero medio di elementi diversi da zero nella rappresentazione intermedia codificata di SAE. La perdita recuperata sostituisce le attivazioni originali di GPT con attivazioni ricostruite e misura la perdita aggiuntiva di risultati di ricostruzione imperfetti. Di solito esiste un compromesso tra questi due parametri, poiché SAE può scegliere una soluzione che si traduce in una diminuzione dell'accuratezza della ricostruzione al fine di migliorare la scarsità.

Quando si confrontano i SAE, un approccio comune consiste nel tracciare le due variabili e quindi esaminare i compromessi tra di loro. Per ottenere compromessi migliori, molti nuovi metodi SAE (come Gated SAE di DeepMind e TopK SAE di OpenAI) hanno modificato la penalità di scarsità. L'immagine qui sotto è tratta dal documento Gated SAE di DeepMind. Il SAE recintato è rappresentato dalla linea rossa, situata nella parte superiore sinistra del grafico, che mostra che funziona meglio con questo compromesso.



SAE L0 recintato e perdita recuperata

Esistono diversi livelli di difficoltà nella misurazione del SAE. L0 e Loss Recovered sono due indicatori proxy. Tuttavia, non li utilizziamo durante l'addestramento perché L0 non è differenziabile e il calcolo delle perdite recuperate durante l'addestramento SAE è molto costoso dal punto di vista computazionale. Invece, la nostra perdita di allenamento è determinata da un termine di penalità L1 e dall’accuratezza della ricostruzione delle attivazioni interne, piuttosto che dal suo impatto sulla perdita a valle.

La funzione di perdita di addestramento non corrisponde direttamente alla metrica surrogata, e la metrica surrogata è solo un proxy per una valutazione soggettiva dell'interpretabilità delle caratteristiche. Poiché il nostro vero obiettivo è "comprendere come funziona il modello" e le valutazioni soggettive di interpretabilità sono solo approssimative, ci sarà un altro livello di discrepanza. Alcuni concetti importanti in LLM potrebbero non essere facili da interpretare e potremmo trascurare questi concetti ottimizzando ciecamente l'interpretabilità.

Riassumere

Il campo della spiegabilità ha ancora molta strada da fare, ma SAE rappresenta un vero progresso. SAE consente nuove interessanti applicazioni, come un metodo non supervisionato per trovare vettori di sterzo come il vettore di sterzo del Golden Gate Bridge. SAE può anche aiutarci a trovare più facilmente loop nei modelli linguistici, che possono essere utilizzati per rimuovere pregiudizi non necessari all'interno del modello.

Il fatto che i SAE possano trovare caratteristiche interpretabili (anche se l’obiettivo è semplicemente identificare modelli nelle attivazioni) suggerisce che possono rivelare qualcosa di significativo. Esistono anche prove del fatto che il LLM può effettivamente apprendere qualcosa di significativo, piuttosto che limitarsi a memorizzare modelli statistici superficiali.

SAE potrebbe anche rappresentare una prima pietra miliare a cui puntavano aziende come Anthropic, vale a dire "MRI (risonanza magnetica) per modelli di apprendimento automatico". SAE non fornisce ancora una comprensione perfetta, ma può essere utilizzato per rilevare comportamenti scorretti. Le principali sfide del SAE e della valutazione SAE non sono insormontabili e molti ricercatori stanno già lavorando su questo argomento.

Per un'ulteriore introduzione agli autoencoder sparsi, fare riferimento al taccuino Colab di Callum McDougal: https://www.lesswrong.com/posts/LnHowHgmrMbWtpkxx/intro-to-superposition-and-sparse-autoencoders-colab

https://www.reddit.com/r/MachineLearning/comments/1eeihdl/d_an_intuitive_explanation_of_sparse_autoencoders/

https://adamkarvonen.github.io/machine_learning/2024/06/11/sae-intuitions.html