MVA project.
Contributors:
Yannis Kolodziej, Tom Mariani, Hai Pham, Valentin Smague
This project investigates how Sparse Autoencoder (SAE) features inside large language models (LLMs) encode language identity. The core metric is the v-score — a per-feature, per-language score that measures how much a SAE feature activates on one language compared to the average across all other languages.
What is the V-Score?
For a given SAE feature f and language L (over a set of K languages):
v(f, L) = mean_activation(f, L) - mean( mean_activation(f, L') for L' ≠ L )
Features with a high v-score for language L are considered language-specific to L. By sorting features by their v-score, we obtain a ranked list of the most language-discriminative SAE features per layer.
Project Structure
MVA-SNLP/
├── compute_v_scores.py # CLI: compute & save v-scores for any model/SAE/language set
├── visualize_v_scores.ipynb # Visualize saved v-score runs (Figure 1 reproduction + insights)
├── sae_feature_exploration.ipynb # Hugging Face-based interactive SAE feature exploration
├── extended_visualization.ipynb # Extended visualizations and additional analyses
├── code_switching_analysis.ipynb # Code-switching analysis on specific words
│
├── scripts/ # Ready-to-run bash scripts for each experiment
│ ├── run_gemma_reprod.sh # Reproduce Figure 1 (Gemma-2B, 10 languages, 100 texts)
│ ├── run_gemma_diverse_langs_all.sh # Insight 1: all texts, 10 diverse languages
│ ├── run_gemma_diverse_langs_small.sh # Insight 1: quick run (25 texts/language)
│ ├── run_gemma_similar_langs.sh # Insight 2: similar languages (es/pt/gl/ca)
│ ├── run_gemma_underrepresented_langs.sh # Insight 4: underrepresented languages
│ └── run_qwen_reprod.sh # Reproduction with Qwen3-0.6B
│
└── v_score_runs/ # Saved results (meta.json + v_scores.pt per run)
├── run_reprod_fig_1/
├── run_insight_1_all/
├── run_insight_1_small/
├── run_insight_2/
├── run_insight_4/
└── qwen_run_reprod_fig_1/
Open visualize_v_scores.ipynb and point it to any v_score_runs/<run_name>/ directory. The notebook loads meta.json and v_scores.pt and renders:
Top language-specific features per layer
Feature activation heatmaps across languages
V-score distributions
CLI Reference
python compute_v_scores.py compute [OPTIONS]
Options:
--model Preset: gemma-2b | qwen3-0.6b | custom
--model-id Override HuggingFace model ID (for --model custom)
--sae-release Override sae_lens release name
--sae-id-template Template string with {layer}, e.g. "layer_{layer}/width_16k/canonical"
--languages Comma-separated flores_plus language codes
--layers Comma-separated layer indices to analyse
--n-texts-per-lang Number of FLORES+ texts per language (default: 100, -1 = all)
--split FLORES+ split: dev | devtest (default: dev)
--out-dir Output directory for meta.json and v_scores.pt
--device cuda | cpu (default: auto-detect)
Language Codes
Languages are specified as FLORES+ codes (lang_Script). Examples:
The v-score runs produced by this repo feed into a companion project that extends the analysis into active language steering using SAE-gated steering vectors:
siemovit/snlp — Unveiling Language-Specific Features in Large Language Models via Sparse Autoencoders (Part 6 experiments)
That repo implements three experiments on top of the v-scores:
Experiment
Entry point
What it does
Baseline steering
part_6/baseline_experiment.py
One-layer toy steering demo
Adversarial Language Identification (LID)
part_6/lid_experiment.py
Steers model to generate in a target language; measures first-token LID accuracy
Cross-Lingual Continuation (CLC)
part_6/clc_experiment.py
Prompts in one language, steers continuation into another
Using v-score runs from this repo in the steering repo
The steering repo can import saved v-score runs directly via its export utility:
VSmague/NLP — Extended experiments by Valentin Smague covering ablation studies, feature clustering, and cross-language synergy analysis built on top of the v-scores from this repo.
That repo covers four additional directions:
Analysis
Script / Notebook
What it does
Feature ablation
ablation.py, SNLP_ablation_clean.ipynb
Ablates top language-specific SAE features and measures the effect on model behavior; produces per-language specificity plots
Language clustering
compute_clusters.py, compute_matrix.py
Clusters languages by their v-score feature overlap using MDS and similarity matrices
Cross-language synergy
cross_language_synergy.py
Measures how much top features for one language also activate on other languages (feature sharing / synergy)
Visualization
visualisation.py, reprod.py
Reproduces v-score bar charts (Figure 1 style) and generates additional plots
Key outputs stored in the repo:
v_scores.png — reproduced v-score figure
ablation_fr.png, ablation_specificity.png — ablation results for French
clustering_best.png, clustering_comparison.png, clustering_mds.png — language clustering visualizations
plots/, plots_interaction/, plots_synergy/ — full plot collections
sae_features/ — saved SAE feature data
figures_section5/ — figures for section 5 of the report