LLaVA-1.5-7B Cross-Layer Transcoders (CLTs)
Overview
This repository contains
Cross-Layer Transcoders (CLTs) trained on
llava-hf/llava-1.5-7b-hf for mechanistic interpretability research. CLTs are sparse autoencoders that decompose dense MLP activations into interpretable features, enabling attribution analysis and feature steering in vision-language models.
Key Features
✅ 31 layers of transcoders (L0-L30) covering all LLaVA language model layers
✅ MLP→CLT mappings for every layer (co-activation based correlation)
✅ Decoder weights for CLT→MLP reconstruction
✅ 0% dead features across all layers
✅ 2-5% average sparsity in early/middle layers (interpretable and efficient)
Architecture
```
Input (MLP hidden state): [batch, seq_len, 4096]
↓
Transcoder Encoder: LayerNorm + Linear(4096 → 8192) + ReLU
↓
Sparse Features: [batch, seq_len, 8192] (~2-5% active)
↓
Transcoder Decoder: Linear(8192 → 4096)
↓
Output (MLP reconstruction): [batch, seq_len, 4096]
```
Parameters per layer:
Hidden dim: 4096
Feature dim: 8192 (2× expansion)
Total parameters per transcoder: ~67M
Sparsity: 2-29% L0 (layer-dependent, deeper layers are sparser)
Training Details
Model : `llava-hf/llava-1.5-7b-hf`
Dataset : ~45K multimodal samples (Flickr30K + instruction tasks)
Steps per layer : 5,000
Learning rate : 3e-4 (AdamW)
Batch size : 16 samples
Sparsity penalty : 0.01 (L1 on features)
Validation : Every 200 steps
Training Quality Metrics
Layer Range Avg Sparsity (L0%) Avg Reconstruction Loss Dead Features L0-L10 2-4% 0.05-0.15 0% L11-L18 3-7% 0.05-0.10 0% L19-L30 7-29% 0.05-0.20 0%
Note : Higher sparsity in deeper layers (L19-L30) is expected behavior in transformers, where later layers are more specialized.
Files
Each layer has two files:
1. `transcoder_L{layer}.pt`
Contains the trained transcoder model and training metadata.
```python
checkpoint = torch.load('transcoder_L5.pt')
Keys: 'layer', 'hidden_dim', 'feature_dim', 'state_dict', 'training_metadata', 'mlp_to_clt_mapping'
```
2. `mapping_L{layer}.pt`
Contains MLP→CLT mapping and decoder weights for analysis.
```python
mapping = torch.load('mapping_L5.pt')
Keys: 'layer', 'mlp_to_clt_mapping', 'decoder_weights', 'hidden_dim', 'feature_dim', 'description'
mlp_to_clt_mapping: [4096, 8192] - which MLP neurons correlate with each CLT feature
decoder_weights: [4096, 8192] - CLT → MLP reconstruction weights
```
Usage
1. Load a Transcoder
```python
import torch
import torch.nn as nn
class Transcoder(nn.Module):
def init (self, hidden_dim: int, feature_dim: int):
super().init ()
self.enc = nn.Sequential(
nn.LayerNorm(hidden_dim),
nn.Linear(hidden_dim, feature_dim),
)
self.dec = nn.Linear(feature_dim, hidden_dim)
def forward(self, x):
z_pre = self.enc(x)
z = torch.relu(z_pre)
y_hat = self.dec(z)
return y_hat, z # reconstruction, features
Load Layer 10 transcoder
checkpoint = torch.load('transcoder_L10.pt', map_location='cpu')
hidden_dim = checkpoint['hidden_dim']
feature_dim = checkpoint['feature_dim']
transcoder = Transcoder(hidden_dim, feature_dim)
transcoder.load_state_dict(checkpoint['state_dict'])
transcoder.eval()
Use with LLaVA MLP outputs
with torch.no_grad():
mlp_output = ... # [batch, seq_len, 4096] from LLaVA layer 10
reconstruction, features = transcoder(mlp_output)
# features: [batch, seq_len, 8192] - sparse interpretable features
# reconstruction: [batch, seq_len, 4096] - reconstructed MLP output
```
2. Use MLP→CLT Mapping
The mapping shows which MLP neurons are correlated with each CLT feature:
```python
mapping_data = torch.load('mapping_L10.pt', map_location='cpu')
mlp_to_clt = mapping_data['mlp_to_clt_mapping'] # [4096, 8192]
Find top MLP neurons for a specific CLT feature
feature_idx = 1234
top_mlp_neurons = mlp_to_clt[:, feature_idx].topk(k=10)
print(f"Top MLP neurons for feature {feature_idx}: {top_mlp_neurons.indices}")
Find top CLT features for a specific MLP neuron
mlp_neuron_idx = 567
top_clt_features = mlp_to_clt[mlp_neuron_idx, :].topk(k=10)
print(f"Top CLT features for MLP neuron {mlp_neuron_idx}: {top_clt_features.indices}")
```
3. Replacement Model (Full Integration)
For direct integration into LLaVA (replace MLPs with CLTs):
```python
from transformers import LlavaForConditionalGeneration
Load LLaVA
model = LlavaForConditionalGeneration.from_pretrained(
"llava-hf/llava-1.5-7b-hf",
torch_dtype=torch.bfloat16,
device_map="auto"
)
Replace MLP in layer 10 with CLT (example)
layer_idx = 10
checkpoint = torch.load(f'transcoder_L{layer_idx}.pt')
transcoder = Transcoder(checkpoint['hidden_dim'], checkpoint['feature_dim'])
transcoder.load_state_dict(checkpoint['state_dict'])
Hook to replace MLP forward pass
def replace_mlp_with_clt(module, input, output):
hidden_state = input[0]
reconstruction, features = transcoder(hidden_state)
return reconstruction
model.model.layers[layer_idx].mlp.register_forward_hook(replace_mlp_with_clt)
```
Applications
1. Feature Attribution
Identify which features contribute to specific model outputs (hallucination detection, sycophancy analysis).
2. Feature Steering
Amplify or suppress specific features at inference time to modify model behavior (reduce hallucinations, improve grounding).
3. Mechanistic Interpretability
Build attribution graphs showing causal relationships between features and outputs.
4. Circuit Discovery
Map feature interactions across layers to understand how the model processes multimodal information.
Related Work
This work extends Anthropic's Circuit-Tracer methodology to multimodal vision-language models:
Citation
If you use these transcoders in your research, please cite:
```bibtex
@misc{llava15_clts_2025,
title={Cross-Layer Transcoders for LLaVA-1.5-7B},
author={Koko's Dev},
year={2025},
publisher={HuggingFace Hub},
howpublished={\url{
https://huggingface.co/KokosDev/llava15-7b-clt}}
}
```
License
These transcoders are released under the same license as the base model (Apache 2.0). The base LLaVA-1.5-7B model is from
llava-hf/llava-1.5-7b-hf .
Acknowledgments
Base Model : LLaVA-1.5-7B
Methodology : Inspired by Anthropic's Circuit-Tracer and sparse autoencoder research
Training Data : Flickr30K, instruction-following datasets