Cette bibliothèque forme des autoencoders (SAES) k -sapare sur les activations résiduelles des modèles de langage HuggingFace, à peu près la recette détaillée dans la mise à l'échelle et l'évaluation des autoencoders clairsemés (Gao et al. 2024).
Il s'agit d'une bibliothèque simple et simple avec quelques options de configuration. Contrairement à la plupart des autres bibliothèques SAE (par exemple Saelens), elle ne cache pas d'activations sur le disque, mais les calcule plutôt à la volée. Cela nous permet d'évoluer vers de très grands modèles et ensembles de données avec des frais généraux de stockage zéro, mais a l'inconvénient que d'essayer différents hyperparamètres pour le même modèle et le même ensemble de données sera plus lent que si nous avons mis en cache des activations (car les activations seront recueillies). Nous pouvons ajouter de la mise en cache en option à l'avenir.
Après Gao et al., Nous utilisons une fonction d'activation de TopK qui applique directement un niveau de rareté souhaité dans les activations. Cela contraste avec d'autres bibliothèques qui utilisent une pénalité L1 dans la fonction de perte. Nous pensons que Topk est une amélioration de Pareto par rapport à l'approche L1, et ne prévoit donc pas de le soutenir.
Pour charger un SAE pré-entraîné à partir du hub étreint, vous pouvez utiliser la méthode Sae.load_from_hub
comme suit:
from sae import Sae
sae = Sae . load_from_hub ( "EleutherAI/sae-llama-3-8b-32x" , hookpoint = "layers.10" )
Cela chargera le SAE pour la couche résiduelle du flux 10 de Llama 3 8b, qui a été formé avec un facteur d'expansion de 32. Vous pouvez également charger les SAE pour toutes les couches à la fois en utilisant Sae.load_many
:
saes = Sae . load_many ( "EleutherAI/sae-llama-3-8b-32x" )
saes [ "layers.10" ]
Le dictionnaire renvoyé par load_many
est garanti d'être naturellement trié par le nom du point de crochet. Pour le cas commun où les points de crochet sont nommés embed_tokens
, layers.0
, ..., layers.n
, cela signifie que les SAE seront triés par numéro de couche. Nous pouvons ensuite rassembler les activations SAE pour un modèle de passe avant comme suit:
from transformers import AutoModelForCausalLM , AutoTokenizer
import torch
tokenizer = AutoTokenizer . from_pretrained ( "meta-llama/Meta-Llama-3-8B" )
inputs = tokenizer ( "Hello, world!" , return_tensors = "pt" )
with torch . inference_mode ():
model = AutoModelForCausalLM . from_pretrained ( "meta-llama/Meta-Llama-3-8B" )
outputs = model ( ** inputs , output_hidden_states = True )
latent_acts = []
for sae , hidden_state in zip ( saes . values (), outputs . hidden_states ):
latent_acts . append ( sae . encode ( hidden_state ))
# Do stuff with the latent activations
Pour former des SAE à partir de la ligne de commande, vous pouvez utiliser la commande suivante:
python -m sae EleutherAI/pythia-160m togethercomputer/RedPajama-Data-1T-Sample
La CLI prend en charge toutes les options de configuration fournies par la classe TrainConfig
. Vous pouvez les voir en exécutant python -m sae --help
.
L'utilisation programmatique est simple. Voici un exemple:
import torch
from datasets import load_dataset
from transformers import AutoModelForCausalLM , AutoTokenizer
from sae import SaeConfig , SaeTrainer , TrainConfig
from sae . data import chunk_and_tokenize
MODEL = "EleutherAI/pythia-160m"
dataset = load_dataset (
"togethercomputer/RedPajama-Data-1T-Sample" ,
split = "train" ,
trust_remote_code = True ,
)
tokenizer = AutoTokenizer . from_pretrained ( MODEL )
tokenized = chunk_and_tokenize ( dataset , tokenizer )
gpt = AutoModelForCausalLM . from_pretrained (
MODEL ,
device_map = { "" : "cuda" },
torch_dtype = torch . bfloat16 ,
)
cfg = TrainConfig (
SaeConfig ( gpt . config . hidden_size ), batch_size = 16
)
trainer = SaeTrainer ( cfg , tokenized , gpt )
trainer . fit ()
Par défaut, les SAE sont formés sur les activations résiduelles du flux du modèle. Cependant, vous pouvez également former des SAE sur les activations de tout autre sous-module en spécifiant les modèles de point de crochet personnalisés. Ces modèles sont comme des noms de modules Pytorch standard (par exemple h.0.ln_1
), mais permettent également une syntaxe de correspondance du modèle UNIX, y compris les caractères génériques et les jeux de caractères. Par exemple, pour former des SAE sur la sortie de chaque module d'attention et les activations intérieures de chaque MLP dans GPT-2, vous pouvez utiliser le code suivant:
python -m sae gpt2 togethercomputer/RedPajama-Data-1T-Sample --hookpoints " h.*.attn " " h.*.mlp.act "
Se limiter aux trois premières couches:
python -m sae gpt2 togethercomputer/RedPajama-Data-1T-Sample --hookpoints " h.[012].attn " " h.[012].mlp.act "
Nous ne prenons actuellement pas en charge le contrôle manuel à grains fins sur le taux d'apprentissage, le nombre de latents ou d'autres hyperparamètres à hook-by hookpoint. Par défaut, l'option expansion_ratio
est utilisée pour sélectionner le nombre approprié de latents pour chaque point de crochet en fonction de la largeur de la sortie de ce hookpoint. Le taux d'apprentissage par défaut pour chaque point de crochet est ensuite défini à l'aide d'une loi de mise à l'échelle de la racine carrée inverse en fonction du nombre de latents. Si vous définissez manuellement le nombre de lameurs ou le taux d'apprentissage, il sera appliqué à tous les points de crochet.
Nous prenons en charge la formation distribuée via la commande torchrun
de Pytorch. Par défaut, nous utilisons la méthode parallèle des données distribuées, ce qui signifie que les poids de chaque SAE sont reproduits sur chaque GPU.
torchrun --nproc_per_node gpu -m sae meta-llama/Meta-Llama-3-8B --batch_size 1 --layers 16 24 --k 192 --grad_acc_steps 8 --ctx_len 2048
C'est simple, mais très inefficace. Si vous souhaitez former des SAE pour de nombreuses couches d'un modèle, nous vous recommandons d'utiliser le drapeau --distribute_modules
, qui alloue les SAE à différentes couches à différents GPU. Actuellement, nous exigeons que le nombre de GPU divise uniformément le nombre de couches pour lesquelles vous entraînez SAES.
torchrun --nproc_per_node gpu -m sae meta-llama/Meta-Llama-3-8B --distribute_modules --batch_size 1 --layer_stride 2 --grad_acc_steps 8 --ctx_len 2048 --k 192 --load_in_8bit --micro_acc_steps 2
La commande ci-dessus forme un SAE pour chaque couche pair de lama 3 8b, en utilisant tous les GPU disponibles. Il accumule des gradients sur 8 minibatchs et divise chaque minibatch en 2 microbatches avant de les nourrir dans le codeur SAE, économisant ainsi beaucoup de mémoire. Il charge également le modèle en précision 8 bits à l'aide bitsandbytes
. Cette commande ne nécessite pas plus de 48 Go de mémoire par GPU sur un nœud de 8 GPU.
Il existe plusieurs fonctionnalités que nous aimerions ajouter dans un avenir proche:
Si vous souhaitez vous aider avec l'un de ces éléments, n'hésitez pas à ouvrir un RP! Vous pouvez collaborer avec nous dans le canal clairsemé des autoencodeurs de la discorde Eleutherai.