Jupyter Notebook
0
2 commits
updated Sep 20, 2026
This repository contains a reproduction and extension of
Pearce et al. (2024), Bilinear MLPs Enable Weight-Based Mechanistic Interpretability.
All experimental results corresponding to Claims 1–4 in the original paper are reproduced, as well as two additional extensions in a single executable notebook.
full_report.ipynbThis notebook reproduces all results reported in the accompanying report, including:
Claim 1 (Image Classification)
Eigenvector decomposition of bilinear MLP weights across image classification tasks reveals an interpretable low-rank structure.
Claim 2 (Image Classification)
Truncating lower-magnitude eigenvalue components has minimal impact on classification performance, indicating that most task-relevant information is captured by the leading eigenvectors.
Claim 3 (Image Classification)
The eigenvectors of bilinear MLPs are stable across random initializations and behave similarly across different model sizes.
Claim 4 (Image Classification)
Input noise regularization reduces overfitting and produces bilinear MLPs with eigenvector features that are more interpretable under eigenvalue analysis
Extension 1 (Adversarial Training on MNIST)
Evaluation of FGSM (Goodfellow et al., 2014) and PGD (Madry et al., 2017) adversarial training on
both robustness and eigenvector interpretability.
Extension 2 (CIFAR-10 / CIFAR-100 / Tiny ImageNet)
Testing whether low-rank structure, eigenvector stability, and truncation robustness generalize
beyond MNIST.
All figures, tables, and metrics in the report are generated by running this notebook top-to-bottom.
The core of this reproducibility study centers on the Bilinear MLP, an architecture designed to facilitate mechanistic interpretability directly from model weights. Unlike standard MLPs that use fixed non-linearities (e.g., ReLU or GeLU), Bilinear MLPs utilize a gated quadratic interaction.
The fundamental transformation in these models replaces the standard activation function with an element-wise product of two linear projections. For an input vector $\mathbf{x}$, the output $\mathbf{y}$ is defined as:
$$\mathbf{y} = (W_1 \mathbf{x} \odot W_2 \mathbf{x})W_3$$
Where:
We evaluate the following architecture:
| Dataset | Characteristics | Size | Access Method |
|---|---|---|---|
| MNIST | 28x28 Grayscale images of handwritten digits (0–9). | 60,000 Train / 10,000 Test. | Automated download via torchvision. |
| Fashion-MNIST | 28x28 Grayscale images of 10 clothing categories. | 60,000 Train / 10,000 Test. | Automated download via torchvision. |
| CIFAR-10 | 32x32 Color (RGB) images across 10 general classes. | 50,000 Train / 10,000 Test. | Automated download via torchvision. |
| CIFAR-100 | 32x32 Color (RGB) images across 100 fine-grained classes. | 50,000 Train / 10,000 Test. | Automated download via torchvision. |
| Tiny ImageNet | 64x64 Color (RGB) images across 200 fine-grained classes. | 100,000 Train / 10,000 Test. | Automated download via torchvision. |
full_report.ipynb notebook without a dedicated GPU.bilinear-decomposition_(cloned_from_authors)/
├── image/ # Image models, datasets, adversarial training code
├── language/ # Transformer language model with bilinear MLPs
├── results/ # Saved models, datasets, emissions logs, figures
├── sae/ # Sparse Autoencoder tools and eigenvector analysis
├── shared/ # Shared bilinear / linear components
├── toy/ # Author-provided toy model configuration
├── tutorials/ # Author-provided reference notebooks
├── .gitignore # Author-provided gitignore
├── requirements.txt
├── readme.md # Author-provided readme of the original repository
environment-cpu.yml # The conda environment to run locally on your CPU
environment-gpu.yml # The conda environment to run on a GPU
full_report.ipynb # Main notebook for reproducing claims + extensions
.gitignore
All implementations use PyTorch.
CPU:
conda env create -f environment-cpu.yml
conda activate fact-ai-cpu
GPU:
conda env create -f environment-gpu.yml
conda activate fact-ai-gpu
Jupyter Notebook
0
2 commits
updated Sep 20, 2026
This repository contains a reproduction and extension of
Pearce et al. (2024), Bilinear MLPs Enable Weight-Based Mechanistic Interpretability.
All experimental results corresponding to Claims 1–4 in the original paper are reproduced, as well as two additional extensions in a single executable notebook.
full_report.ipynbThis notebook reproduces all results reported in the accompanying report, including:
Claim 1 (Image Classification)
Eigenvector decomposition of bilinear MLP weights across image classification tasks reveals an interpretable low-rank structure.
Claim 2 (Image Classification)
Truncating lower-magnitude eigenvalue components has minimal impact on classification performance, indicating that most task-relevant information is captured by the leading eigenvectors.
Claim 3 (Image Classification)
The eigenvectors of bilinear MLPs are stable across random initializations and behave similarly across different model sizes.
Claim 4 (Image Classification)
Input noise regularization reduces overfitting and produces bilinear MLPs with eigenvector features that are more interpretable under eigenvalue analysis
Extension 1 (Adversarial Training on MNIST)
Evaluation of FGSM (Goodfellow et al., 2014) and PGD (Madry et al., 2017) adversarial training on
both robustness and eigenvector interpretability.
Extension 2 (CIFAR-10 / CIFAR-100 / Tiny ImageNet)
Testing whether low-rank structure, eigenvector stability, and truncation robustness generalize
beyond MNIST.
All figures, tables, and metrics in the report are generated by running this notebook top-to-bottom.
The core of this reproducibility study centers on the Bilinear MLP, an architecture designed to facilitate mechanistic interpretability directly from model weights. Unlike standard MLPs that use fixed non-linearities (e.g., ReLU or GeLU), Bilinear MLPs utilize a gated quadratic interaction.
The fundamental transformation in these models replaces the standard activation function with an element-wise product of two linear projections. For an input vector $\mathbf{x}$, the output $\mathbf{y}$ is defined as:
$$\mathbf{y} = (W_1 \mathbf{x} \odot W_2 \mathbf{x})W_3$$
Where:
We evaluate the following architecture:
| Dataset | Characteristics | Size | Access Method |
|---|---|---|---|
| MNIST | 28x28 Grayscale images of handwritten digits (0–9). | 60,000 Train / 10,000 Test. | Automated download via torchvision. |
| Fashion-MNIST | 28x28 Grayscale images of 10 clothing categories. | 60,000 Train / 10,000 Test. | Automated download via torchvision. |
| CIFAR-10 | 32x32 Color (RGB) images across 10 general classes. | 50,000 Train / 10,000 Test. | Automated download via torchvision. |
| CIFAR-100 | 32x32 Color (RGB) images across 100 fine-grained classes. | 50,000 Train / 10,000 Test. | Automated download via torchvision. |
| Tiny ImageNet | 64x64 Color (RGB) images across 200 fine-grained classes. | 100,000 Train / 10,000 Test. | Automated download via torchvision. |
full_report.ipynb notebook without a dedicated GPU.bilinear-decomposition_(cloned_from_authors)/
├── image/ # Image models, datasets, adversarial training code
├── language/ # Transformer language model with bilinear MLPs
├── results/ # Saved models, datasets, emissions logs, figures
├── sae/ # Sparse Autoencoder tools and eigenvector analysis
├── shared/ # Shared bilinear / linear components
├── toy/ # Author-provided toy model configuration
├── tutorials/ # Author-provided reference notebooks
├── .gitignore # Author-provided gitignore
├── requirements.txt
├── readme.md # Author-provided readme of the original repository
environment-cpu.yml # The conda environment to run locally on your CPU
environment-gpu.yml # The conda environment to run on a GPU
full_report.ipynb # Main notebook for reproducing claims + extensions
.gitignore
All implementations use PyTorch.
CPU:
conda env create -f environment-cpu.yml
conda activate fact-ai-cpu
GPU:
conda env create -f environment-gpu.yml
conda activate fact-ai-gpu