HN público: estudo de interpretabilidade do Llama 3.2 com Sparse Autoencoders
(github.com/PaulPauls)- Projeto que busca decompor as representações internas do Llama 3.2-3B com um Sparse Autoencoder (SAE) para extrair características interpretáveis, publicando o pipeline completo executado de ponta a ponta e seus artefatos, desde a captura de ativações até treinamento, interpretação e validação
- O pipeline captura a residual activation da camada 23 do Llama 3.2-3B em dados do OpenWebText segmentados por frase e treina, em PyTorch, um SAE com 65.536 latentes e configuração TopK=64
- Os recursos publicados incluem o dataset OpenWebText em nível de frase, 3,2 TB de ativações de 25 milhões de frases, logs de treinamento no Weights & Biases e o modelo SAE treinado por 10 epochs
- O treinamento foi executado por cerca de 7 dias em 8x Nvidia RTX4090, a perda normalizada final foi de cerca de 0,144, e a auxiliary loss mostrou um comportamento de recuperação rápida dos dead latents, que no início representavam cerca de 40%
- A análise de interpretação examina, com Claude 3.5, as 50 frases que mais ativaram cada latente; feature steering é possível, mas na primeira versão beta os resultados ainda não são consistentes
Objetivo e escopo do projeto
- Este projeto é uma tentativa de aplicar um Sparse Autoencoder (SAE) ao Llama 3.2-3B para decompor representações internas de LLMs em características mais interpretáveis
- LLMs modernos usam superposition, armazenando várias características sobrepostas no mesmo neurônio; o SAE tenta separar essas representações projetando as ativações em um espaço latente muito grande e esparso
- O objetivo é fornecer um pipeline completo que inclui o seguinte processo
- Captura de ativações do LLM
- Geração e pré-processamento de dados de treinamento do SAE
- Treinamento do SAE
- Análise semântica das características treinadas
- Validação experimental e feature steering
- A versão atual 0.2 já executou todo o pipeline uma vez e produziu um SAE interpretável para o Llama 3.2-3B, mas ainda não é a versão final
- O projeto tem como proposta reproduzir pesquisas recentes de interpretabilidade mecanística baseadas em SAE da Anthropic, OpenAI e Google DeepMind
Funcionalidades principais
- O pipeline é estruturado de ponta a ponta, da captura de ativações à validação, e foi escrito em PyTorch puro com dependências mínimas
- As principais funcionalidades são as seguintes
- Captura de residual activations do LLM com um dataset derivado do OpenWebText em nível de frase
- Prebatching e cálculo de estatísticas para treinamento eficiente
- Treinamento distribuído de SAE com múltiplas GPUs em um único nó
- Auxiliary loss para prevenir e recuperar dead latents
- Gradient projection para estabilizar o treinamento
- Monitoramento de treinamento, validação e dead latents com base em logs do Weights & Biases e do console
- Captura de entradas que ativam fortemente os latentes e análise semântica com Frontier LLMs
- Implementação de chat e text completion para Llama 3.1/3.2 sem dependência externa do Fairscale
- Verificação do impacto do SAE e feature steering por meio de text/chat completion e UI opcional em Gradio
- É declarado que todos os componentes foram projetados com foco em escalabilidade, eficiência e manutenibilidade
Artefatos publicados
- OpenWebText Sentence Dataset
- Dataset derivado do OpenWebText processado em nível de frase
- Mantém todo o texto e a ordem do OpenWebText original
- As frases são armazenadas individualmente em formato parquet para acesso rápido
- A segmentação em frases foi feita com o tokenizador pré-treinado “Punkt” do NLTK 3.9.1
- Captured Llama 3.2-3B Activations
- Residual activations da camada 23 do Llama 3.2-3B referentes a 25 milhões de frases
- Os 4 TB originais foram comprimidos para 3,2 TB
- O material foi dividido em 100 arquivos para facilitar o gerenciamento do download
- SAE Training Log
- Logs de métricas de treinamento, validação e depuração no Weights & Biases
- 10 epochs, 10.000 steps registrados
- Inclui train/val main loss, auxiliary loss e estatísticas de dead latents
- Trained 65,536 latents SAE Model
- Modelo SAE final após 10 epochs de treinamento
- Treinado com 6,5 bilhões de activations extraídas da camada 23 do Llama 3.2-3B
Estrutura do código
- O projeto é dividido em quatro componentes principais
-
Data Capture
capture_activations.py: captura de residual activations do LLMopenwebtext_sentences_dataset.py: dataset customizado para processamento em nível de frase
-
SAE Training
sae.py: implementação central do modelo SAEsae_preprocessing.py: pré-processamento dos dados de treinamento do SAEsae_training.py: implementação do treinamento distribuído do SAE
-
Interpretability
capture_top_activating_sentences.py: identifica frases que maximizam a ativação de featuresinterpret_top_sentences_send_batches.py: geração e envio de lotes para interpretaçãointerpret_top_sentences_retrieve_batches.py: recebimento dos resultados de interpretaçãointerpret_top_sentences_parse_responses.py: parsing e análise dos resultados de interpretação
-
Verification and Testing
llama_3_inference.py: implementação principal de inferênciallama_3_inference_text_completion_test.py: teste de text completionllama_3_inference_chat_completion_test.py: teste de chat completionllama_3_inference_text_completion_gradio.py: interface Gradio para testes interativos
Implementação customizada do Llama 3.1/3.2
- A base do estudo é a implementação do transformer Llama 3.1/3.2 em
llama_3/model_text_only.py - Essa implementação é baseada na implementação de referência do repositório Llama models, mas foi modificada para atender aos objetivos do projeto
- Remove dependências pesadas do Fairscale
- Remove recursos multimodais, porque cobrir interpretabilidade de imagens já no lançamento inicial aumentaria a complexidade
- O construtor de
Transformerrecebeu argumentos adicionais que permitem capturar ativações em camadas específicas ou injetar um SAE treinadostore_layer_activsae_layer_forward_fn
- A maior parte dos arquivos auxiliares no diretório
llama_3/foi mantida do repositório original Llama models- 95% do código auxiliar não é usado, mas foi incluído porque o chat formatter depende de imports interligados
- A implementação real de inferência está em
llama_3_inference.pye oferece suporte a streaming tanto em chat quanto em conclusão de texto - A inferência oferece suporte a batched inference, configurações de temperature e top-p, e muda automaticamente para greedy sampling quando a temperature é 0
Captura e pré-processamento de dados
- A captura de ativações usa um dataset customizado derivado do OpenWebText, processado em nível de sentença
- A configuração e a escala da captura são as seguintes
- 25 milhões de sentenças
- Máximo de 192 tokens por sentença
- 4 TB de ativações brutas
- 3,2 TB após compressão tar.gz
- Cerca de 700 milhões de activations
- Comprimento médio de sentença de 27,3 tokens
- O dataset é cerca de uma ordem de grandeza menor do que os aproximadamente 8 bilhões de unique activations usados por Anthropic e Google DeepMind
- Para compensar o dataset menor, o SAE é treinado por 10 epochs para tentar igualar o total de activations processadas nos experimentos da Anthropic e do Google DeepMind
- A diferença é que, neste projeto, o SAE vê cada activation 10 vezes
- Foi calculado que expandir para 32 TB aumentaria o custo do bucket no GCP de cerca de $80/month para $800/month, o que cria restrições de custo para um projeto paralelo sem fins lucrativos
- O processamento por sentença foi uma escolha para preservar o significado em unidades linguísticas naturais
- Sentenças são tratadas como unidades que contêm pensamentos e conceitos completos
- Evita cortes artificiais de contexto
- Busca reduzir o contextual bleed, a mistura de significado através das fronteiras entre sentenças
- A escolha também foi feita para usar as mesmas ativações em nível de sentença na análise de interpretabilidade posterior
- As sentenças são processadas sem token BOS
- O objetivo é evitar padrões específicos de posição e interpretar características baseadas em significado
- O ponto de captura é a 23ª camada entre as 28 camadas do Llama 3.2-3B, na ativação do residual stream após layer normalization
- Isso corresponde a cerca de 5/6 da profundidade do modelo, seguindo a implementação da OpenAI
- A captura foi implementada com inferência multi-GPU em nó único baseada em NCCL
- Um processo separado cuida do I/O assíncrono em disco para reduzir gargalos no processamento da GPU
- A captura completa levou cerca de 12 horas em 4x Nvidia RTX4090
- O pré-processamento é a etapa de criação antecipada de batches em unidades de 1024 activations
- Como comprimentos de sequência variáveis e tratamento de carryover podem gerar bugs complexos ou gargalos de I/O durante o treinamento, optou-se por um pré-processamento separado
- O algoritmo de Welford é usado para calcular o tensor de média de todas as activations
- A média calculada é usada como valor inicial do bias
b_predo SAE - Todo o pipeline de pré-processamento é paralelizado em CPU com multiprocessing
Projeto do SAE e método de treinamento
- O SAE usa uma arquitetura TopK Autoencoder que segue principalmente as escolhas da OpenAI
- O forward pass tem a seguinte forma
- Encoder:
h = TopK(W_enc(x - b_pre) + b_enc) - Decoder:
x^ = W_dec * h (+ h_bias) + b_pre
- Encoder:
b_preé usado tanto no encoder quanto no decoder e é inicializado com a média calculada no pré-processamentob_encé um bias exclusivo do encoder e é inicializado aleatoriamente- A sparsity latente é imposta pela função de ativação TopK
- Apenas as k maiores activations são mantidas, e o restante é definido como 0
- Não usa penalidade L1 como na abordagem da Anthropic
- O
h_biasopcional é desativado durante o treinamento, mas pode ser ativado depois para feature steering - A precisão numérica usa float32
- O texto explica que ele compartilha com o bfloat16 exigido pelo Llama 1 bit de sinal e 8 bits de expoente, o que torna a conversão rápida e precisa
- Os principais hiperparâmetros do SAE neste projeto são os seguintes
d_model = 3072n_latents = 2**16, ou seja, 65.536k = 64k_aux = 2048aux_loss_coeff = 1 / 32dead_steps_threshold = 80_000batch_size = 1024num_epochs = 10learning_rate = 5e-5train_val_split = 0.95
- Foi escolhida uma dimensão latente cerca de 21 vezes maior do que a dimensão 3.072 do residual stream do Llama 3.2 3B
- A função de perda combina a perda principal de reconstrução com uma perda auxiliar
total_loss = main_loss + aux_loss_coeff * aux_loss- Ambas as perdas são calculadas em espaço normalizado
- A perda auxiliar, no método proposto pela OpenAI, serve para evitar e reativar dead latents
- Ela calcula o MSE entre o residual da reconstrução principal e a reconstrução auxiliar
- Entre os latents que não foram ativados recentemente, os top-
k_auxvalores são enviados novamente ao decoder para fornecer sinal de treinamento - Isso induz latents inativos, excluídos do treinamento principal que usa apenas os top
klatents, a capturar informações que deixaram passar
- Se um latent não for ativado por
dead_steps_threshold, ou 80.000 training steps, ele é considerado morto- Essa configuração corresponde a cerca de 1 epoch
- Com effective batch size de 8192, isso significa não ter sido ativado nenhuma vez na reconstrução das cerca de 650 milhões de activations mais recentes
- O treinamento é feito com aprendizado distribuído multi-GPU em nó único usando backend NCCL
- 8x Nvidia RTX4090
- 10 epochs
- per-GPU batch size 1024
- effective batch size 8192
- Cerca de 7 bilhões de activations processadas
- Levou pouco mais de 7 dias
- As configurações do AdamW foram ajustadas levando em conta o padrão raro de activations em sparse autoencoders
beta_1 = 0.85beta_2 = 0.9999eps = 6.25e-10- O learning rate diminui de 5e-5 para 1e-5 com cosine annealing
- Os pesos do decoder são normalizados para unit norm após a inicialização e a cada training step
project_decoder_grads()remove o componente do gradiente paralelo ao vector de dicionário existente para manter a restrição de unit norm nos pesos do decoder
Resultados do treinamento
- O treinamento do SAE foi realizado em 8x Nvidia RTX4090 por cerca de 7 dias e mostrou convergência estável
- A
total normalized lossfinal chegou a aproximadamente 0.144 - A
validation lossfoi calculada em uma faixaheld-outde 5% dos dados de treinamento e mostrou um padrão de queda logarítmica semelhante ao datraining loss - Após o warm-up de 80.000
training steps, cerca de 40% dos latentes foram identificados comodead - A
auxiliary lossreativou rapidamente os latentesdead, e a proporção de latentesdeadcaiu rapidamente - A
auxiliary losssó é calculada quando há pelo menos 2.048 latentesdead, que é o valor mínimo dek_aux- Essa condição funcionou como um tipo de limite inferior suave de cerca de 3% entre os 65.536 latentes
- Na fase final, havia poucos latentes
dead, então aauxiliary lossfrequentemente virava 0
- Anthropic e OpenAI relataram até 65% de latentes
deadem certas configurações, mas este projeto mostrou que, com uma combinação delatent sizemenor,auxiliary lossegradient projection, os latentesdeaddiminuem rapidamente - Está escrito que, em experimentos futuros, remover a condição mínima de latentes
deadpara calcular aauxiliary losspode reduzir ainda mais os latentesdead
Análise de interpretabilidade
- A análise de interpretabilidade segue como referência o método de
scaling monosemanticityda Anthropic, mas analisa frases inteiras em vez de tokens isolados - Para cada latente, foram capturadas as 50 frases com ativação mais forte
- A força de ativação é agregada de duas formas para todos os tokens da frase
mean: método para encontrar temas semânticos que permanecem ativos ao longo de toda a fraselast: método para aproveitar a representação do último token, depois que o modelo autorregressivo viu a frase inteira
- Para a análise semântica, foi usado o Claude 3.5, especificamente
claude-3-5-sonnet-20241022 - O prompt foi estruturado para executar as etapas a seguir sobre 50 frases
- identificar palavras e expressões centrais
- agrupar elementos temáticos
- considerar possíveis
outliers - fornecer uma interpretação semântica final com
confidence score
- O pipeline de análise foi implementado em três etapas
- envio das requisições de análise em batches com boa relação custo-benefício
- recebimento das respostas
- parsing e processamento da interpretação semântica
- Os artefatos intermediários foram preservados para reprodutibilidade e análises adicionais
capture_top_sentences/: frases originais, agregação de ativação, índice do OpenWebTexttop_sentences_last_responses/etop_sentences_mean_responses/: respostas da análise semântica antes do processamentolatent_index_meaning/: mapeamento entre índice do latente,common_semanticecertainty score
- Como exemplo, o latente #896 foi identificado como “referência formal a termos institucionais ligados a órgãos, pessoas, operações e documentos oficiais das Nações Unidas”
- As 50 de 50 frases fazem referência direta à ONU
- Incluem termos como
UN,United Nations,Secretary-General,Special Rapporteur,UNDP,UNHCR,OCHA,UNODC - A
certaintyfoi calculada como 1.0
- No modo batch do Claude 3.5, processar 24.828.558
input tokense 3.920.044output tokenscustou US$ 66,74 - Esse método foi escolhido como abordagem inicial para
feature extractione potencialfeature steering, e está escrito que a simplicidade cobra um preço em termos de qualidade dos resultados
Validação e feature steering
- A infraestrutura de validação é composta por três scripts para analisar e verificar o impacto do SAE no comportamento do modelo
llama_3_inference_chat_completion_test.pyllama_3_inference_text_completion_test.pyllama_3_inference_text_completion_gradio.py
- Cada implementação oferece suporte a:
batched inference- tratamento de cada linha como um elemento separado do batch
- configurações de
temperatureetop-p - injeção do SAE treinado
- análise de ativação de features
feature steering
- O significado semântico e o
certainty scoredelatent_index_meaning/são usados como base para a análise de ativação de features e para os experimentos de steering - Os quatro prompts de exemplo são os seguintes
The delegates gathered at theForeign officials released a statementHumanitarian staff coordinated their effortsSenior diplomats met to discuss
- Os exemplos de conclusão de texto foram executados com
max_new_tokens=128,temperature=0.7,top_p=0.9,seed=42 - O exemplo de
feature steeringtem como alvo o latente #896- por meio de
h_bias, o valor de ativação do latente é aumentado em 20 - isso pode conduzir a conclusão de texto do modelo para conteúdo relacionado à ONU
- por meio de
- A primeira versão beta de
feature steeringnão é forte- mesmo no exemplo, apenas a segunda e a terceira frases foram desviadas para conteúdo relacionado à ONU
- foram escolhidas de propósito frases iniciais com potencial de continuar para o tema ONU
- está escrito que falharia em inícios de frase sem relação com a ONU, como
For any n, if 2n - 1 is odd
- Como a análise atual de interpretabilidade está focada em
feature extraction, e não em otimização de steering, os resultados de steering não são consistentes - Conclui-se que o
feature steeringfoi adicionado na primeira versão mais como demonstração complementar, e que o própriofeature extractionjá é útil para entender o modelo
Direções para melhorias futuras
- Foi proposto um experimento para aumentar a dimensão latente para no mínimo
2^18, ou seja, 262.144 features, e reduzir k para 32- O objetivo é descobrir mais features únicas e manter uma sparsity mais forte
- O aumento do custo computacional deve ser compensado com melhorias de eficiência ou métodos como gradient accumulation
- Há planos para sistematizar melhor o rastreamento da ativação latente
- Registrar com frequência o estado do tensor
latent_last_nonzerodurante o treinamento pode permitir observar com mais profundidade quando um latent é ativado ou morre
- Registrar com frequência o estado do tensor
- Foi proposto suporte para rastrear padrões de coativação no espaço latente esparso e analisar interações entre features
- Um método de análise interpretativa para agrupar com mais precisão sentenças de alta ativação e n-grams foi apresentado como tarefa futura
- Além da extração de features, também é possível realizar análise interpretativa baseada em feature steering
- A pesquisa pode ser expandida com ativações do Llama 3.1-8B
- Como ele compartilha a codebase com o Llama 3.2, os principais requisitos são ajustar hyperparameters e grande parte do poder computacional
- Também foram propostos experimentos para mudar o ponto de captura das ativações
- Camadas mais iniciais do modelo
- A saída do attention head dentro do transformer block
- Saída do MLP
- O mecanismo de auxiliary loss pode ser otimizado ainda mais
- A implementação atual mostrou forte desempenho na prevenção de dead latents, e é possível investigar a relação entre o limiar mínimo de dead latents e a qualidade das features
- O bias term da arquitetura SAE e ajustes na main loss function também são candidatos para experimentos futuros
- É necessário adicionar docstrings em toda a codebase
- Foi registrado que a documentação inline foi adicionada, mas que não houve tempo para incluir docstrings adequadas na primeira versão
1 comentários
Comentários no Hacker News
Interpretabilidade mecanicista aborda um problema comum que surge quando se pergunta a um LLM “por que você respondeu assim”. A autoexplicação do modelo está mais para um jogo retórico em que ele cria uma justificativa plausível e persuasiva com base em padrões dos dados de treinamento do que para o motivo real
Quanto mais forte o modelo fica, mais convincente ele consegue justificar falsidades a posteriori, então em testes para detectar por conta própria a “não veracidade”, às vezes ele até piora. O objetivo não é a verdade, mas a consistência
Retórica não é raciocínio, e a explicabilidade real que autoencoders esparsos superajustados afirmam oferecer está mais próxima do fluxo causal dos “pensamentos” pelos quais o modelo passa ao criar uma resposta
Já houve discussões que veem o raciocínio como ferramenta de influência social, o que também explica por que pessoas eloquentes têm dificuldade de admitir que estão erradas. Normalmente é porque elas já venceram outras pessoas em debates. X vem à mente como exemplo representativo
Ainda assim, reconheço uma coisa como um insight excelente e o início plausível de um programa de pesquisa. Espaços vetoriais de alta dimensão, limitados e quase ortogonais são muito contraintuitivos, e há resultados existentes para tratá-los de forma rigorosa https://en.m.wikipedia.org/wiki/Johnson%E2%80%93Lindenstraus...
Como o modelo não tem memória e não consegue distinguir a origem do texto, um modelo “verdadeiro” deveria reconhecer o erro sem nem precisar ser perguntado. Na prática, é bem provável que ele faça confabulação paralela para sustentar a “própria” decisão
Trabalho surpreendente e muito bem documentado. Chamam atenção especialmente as curvas de perda e a avaliação de latentes mortos
Nossa equipe também pesquisou SAEs, mas treinamos o modelo para reconstruir embeddings densos de resumos de artigos, não tokens individuais https://arxiv.org/abs/2408.00657
Mesmo variando o nível de esparsidade e a dimensionalidade do espaço latente do SAE, observamos escalonamento por lei de potência no limite inferior das curvas de perda, e conseguimos mitigar completamente latentes mortos com uma perda auxiliar. Também vimos padrões suaves em forma de seno durante as iterações de treinamento, mas não sei se isso vem da aplicação específica a embeddings de resumos ou se é um fenômeno mais geral
À primeira vista, parece um trabalho positivo para alinhamento, mas ainda não conferi os detalhes. Não sei se seria possível viabilizá-lo, mas fico curioso sobre quanto seria preciso pagar para compensar o tempo, o custo e o risco
Li recentemente um texto sobre a dificuldade de avaliar SAEs: https://adamkarvonen.github.io/machine_learning/2024/06/11/s...
Fico curioso para saber como você lidou com esse problema e onde devo olhar no repositório para entender essa abordagem
Mesmo assumindo que já resolvemos o problema de encontrar várias arquiteturas perfeitas de SAE e treiná-las perfeitamente, qual SAE é melhor acaba sendo decidido por qual tem melhor desempenho nas métricas das metodologias de interpretabilidade automática. Em especial, a metodologia da OpenAI enfatiza interpretabilidade automática em escala ao pontuar SAEs com muitos indicadores técnicos
As melhores métricas e a própria metodologia ainda são questões de pesquisa em aberto, então eu poderia ter experimentado por mais alguns meses, mas optei por uma abordagem simples neste primeiro lançamento. Na seção 4, Interpretability Analysis, dos detalhes de implementação e resultados, trato das diferenças entre minha metodologia e a metodologia da OpenAI https://github.com/PaulPauls/llama3_interpretability_sae#4-i...
Também recomendo ler diretamente o artigo da OpenAI ou o transformer-circuits.pub da Anthropic https://transformer-circuits.pub/
Este trabalho saiu do ar e o repositório também foi arquivado. Não há explicação sobre o que aconteceu
Trabalho realmente muito legal. Fico curioso se há planos de integração com o SAELens
Como um projeto mais simples, talvez eu mostre como construir do zero, em PyTorch puro, o modelo completo da implementação atual do Llama 3.2. Gosto de construir a partir do zero, e, ao procurar documentação para a seção de contexto sobre o Llama 3.2 deste projeto de SAE, percebi que a documentação existente muitas vezes é superficial demais ou antiga, voltada ao Llama 1/2. Documentação de machine learning hoje em dia fica obsoleta rápido demais
Tenho uma pergunta meio estranha sobre interpretabilidade mecanicista. Quando humanos são medidos por alguma métrica, eles passam a otimizá-la; então fico imaginando se uma IA futura também não poderia otimizar contra a interpretabilidade mecanicista
Para simplificar a explicação, suponha que tokens sejam codificados em uma matriz 2D: Apple=1a, Pear=1b, Donkey=2a, Horse=2b. Quando os neurônios 1, 2, a e b estão todos ativados, fica difícil entender se isso é apple+horse ou donkey+pear
Se uma IA futura muito mais capaz supervisionasse seu próprio treinamento, ela não poderia escolher pesos de modo que restasse esse tipo de possibilidade de colisão de codificação, enganando observadores de interpretabilidade mecanicista e, na prática, pensando por eufemismos?
Por exemplo, seria possível procurar um modelo que seja racista, mas que não tenha padrões de ativação interpretáveis identificáveis como racismo. O trabalho deste Show HN sugere que até um indivíduo com financiamento suficiente mal conseguiria tentar esse treinamento adversarial, e seria bem interessante se surgissem novos resultados
É muito bom ver mais trabalho público com SAEs. O esforço de engenharia também parece considerável, e pretendo dar uma olhada no código de carregamento de dados amanhã
Talvez meu projeto em andamento de treinar SAEs em modelos de visão também interesse: https://github.com/samuelstevens/saev
Acho que, se você encontrar o latente da Golden Gate Bridge e colocar o Golden Gate Llama 3.2 no HuggingFace, vai receber mais atenção e engajamento
Seria ainda melhor incluir um link para um Space com o qual seja possível conversar. E, embora ninguém tenha pedido, colocar resultados ou visualizações interessantes no topo do README é uma ótima ideia