Light activation denoiser for steering — Llama-3.2-1B, layer 7
A 55M-parameter denoiser that repairs the damage activation steering does to a
language model's residual stream, at one forward pass per token — a low-cost
stand-in for GLP's flow-matching activation model (0.5–3.3B parameters, 20 passes).
Trained on 8M activations from blocks.7.hook_resid_post of Llama-3.2-1B,
the exact hook point GLP uses. Steering directions come from the SAE
chanind/sae-llama-3.2-1b-topk-res (d_sae 16384, top-k 10).
Files
| File | Size | What it is |
|---|
F_cond_N8.pt | 220 MB | Main checkpoint. ResMLP K=2 m=2, conditioned on steering strength, 55 072 897 parameters. Every number in the report labelled main_C1 uses this. |
F_cheap_N8.pt | 120 MB | Half-size variant (29.9M). Indistinguishable from the main one on generation; use it if cost matters. |
scaler.pt | 18 KB | Mandatory. Frozen per-dimension standardisation the denoisers live in. Without it the checkpoints produce garbage. |
extraction_summary.json | < 1 KB | E‖h‖ = 4.8955 (sets alpha = r · E‖h‖) and E‖x‖ = 45.12 (the conditioning scale). |
vectors_v2.pt | 490 KB | Frozen validation directions: 32 SAE decoder directions + 5 DiffMean concept vectors. |
val_features_v2.yaml | 12 KB | Which SAE features, their corpus max_act (normalises the concept score), cohort labels, top tokens. |
prefixes.json | 24 KB | Frozen OpenWebText generation prefixes, so a rerun sees the same inputs. |
Quick start
1git clone https://github.com/artemmavrov/light_denoising_for_activation_in_LLM
2cd light_denoising_for_activation_in_LLM
3pip install -r requirements.txt
4
5# fetches this repo, prints steered vs. denoised continuations side by side
6PYTHONPATH=src python scripts/quickstart.py --demo
7
8# reduced sweep + paired bootstrap, compares against the published intervals
9PYTHONPATH=src python scripts/quickstart.py --repro
Needs a GPU with ≥ 6 GB free (Llama-3.2-1B fp16 + the denoiser). Access to
meta-llama/Llama-3.2-1B is gated; the ungated mirror unsloth/Llama-3.2-1B
works and is what the config points at.
Using it directly
1import torch
2from lds.activations import Scaler
3from lds.correction import Intervention, unit
4from lds.denoisers.io import load_denoiser
5from lds.model import load_lm, intervene_layer
6
7bundle = load_lm("unsloth/Llama-3.2-1B", dtype="float16", layer=7)
8scaler = Scaler.load("scaler.pt", device=str(bundle.device))
9denoiser = load_denoiser("F_cond_N8.pt", bundle.d_model, device=str(bundle.device))
10
11v_hat = unit(my_direction).to(bundle.device) # unit-norm steering direction
12alpha = 1.0 * 4.8955 # r * E||h||
13
14intervention = Intervention(
15 v_hat=v_hat, alpha=alpha, scheme="C1", # C0 = plain steering, C1 = denoised
16 denoiser=denoiser, scaler=scaler, x_norm=45.12,
17)
18with intervene_layer(bundle, intervention):
19 out = bundle.model.generate(**inputs, max_new_tokens=48)
scheme selects the correction: C0 plain h + αv, C1 full denoising,
C2 partial (s + λΔ), C5 norm-preserving, C6 multi-step.
What it does and when it helps
The denoiser acts as a learned soft clamp: it removes 81% of the steering
along v at r = 2, yet its output stays at a constant Mahalanobis distance
(37–39) from the clean activation distribution while the steered input drifts
from 53 to 122. It does not undo the intervention — it brings an impossible
feature level back to a plausible one.
Established, replicated result — less degenerate text at any steering strength:
| Δrep-3 vs. plain steering (95% CI, paired over 32 directions) |
|---|
r = 1.5 | −0.065 [−0.113, −0.025] |
r = 2.0 | −0.112 [−0.185, −0.047], 28 of 32 directions |
On 5 DiffMean concepts with objective scorers it wins on both axes:
Δconcept = +0.136 [+0.020, +0.274] at r = 2, at NLL 7.31 vs. 8.28.
Where it does not help. The concept gain on SAE features is conditional and,
averaged over all 32, negative. The sign is predicted by whether plain steering
collapses on that direction: correlation between "retention" and the denoiser's
gain is −0.62 [−0.75, −0.42]. Where steering collapses the denoiser wins in
16 of 17 directions; where it holds up, in 5 of 15.
Cheaper alternative for SAE features. Calibrating α so the feature lands at
the top of its natural range gives the same concept as this checkpoint
(0.01945 vs. 0.01946) at 1.56 nats lower NLL and zero inference cost. The mean
calibrated r is 0.52. See report §6 — this is a negative result for the method
and is reported as such.
Cost
| Parameters | Passes/token | FLOPs vs. one LM forward |
|---|
F_cond_N8 | 55.07M | 1 | 4.46% |
F_cheap_N8 | 29.91M | 1 | 2.4% |
| flow matching, same budget | 55.07M | 19 | 84.67% |
Caveats
- One model, one layer, one SAE (
l0 = 10, 61.8% explained variance).
- The SAE-family concept metric is partly self-referential: the same SAE both
supplies the steering direction and scores the generated text.
- The LLM-judge concept criterion was measured and withdrawn (false-positive
rate 0.259, position inconsistency 0.38). The fluency axis is validated
(
r = −0.96 against NLL).
- fp16 throughout (trained on a Tesla T4, which has no bf16).