Views
No views yet

| Property | Value |
|---|---|
| Base model | Qwen3.5-9B |
SAE width (d_sae) | 65536 |
Hidden size (d_model) | 4096 |
| Expansion factor | 16× |
| Top-K | 50 |
| Hook point | Residual stream |
| Layers covered | 0 – 31 (32 layers total) |
| File format | PyTorch .pt dict |
layer{n}.sae.pt is a Python dict with four tensors:| Key | Shape | Description |
|---|---|---|
W_enc | (65536, 4096) | Encoder weight matrix |
W_dec | (4096, 65536) | Decoder weight matrix |
b_enc | (65536,) | Encoder bias |
b_dec | (4096,) | Decoder bias |
layer0.sae.pt
layer1.sae.pt
...
layer31.sae.pt1import torch
2from transformers import AutoTokenizer, AutoModelForCausalLM
3
4# ── 1. Load base model ────────────────────────────────────────────────────────
5model_name = "Qwen/Qwen3.5-9B"
6tokenizer = AutoTokenizer.from_pretrained(model_name)
7model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float32)
8model.eval()
9
10# ── 2. Load SAE for a target layer ───────────────────────────────────────────
11LAYER = 0 # choose any layer in 0–31
12sae = torch.load(f"layer{LAYER}.sae.pt", map_location="cpu")
13W_enc = sae["W_enc"] # (65536, 4096)
14b_enc = sae["b_enc"] # (65536,)
15
16def get_feature_acts(residual: torch.Tensor) -> torch.Tensor:
17 """residual: (..., 4096) → sparse feature activations (..., 65536)"""
18 pre_acts = residual @ W_enc.T + b_enc
19 topk_vals, topk_idx = pre_acts.topk(50, dim=-1)
20 acts = torch.zeros_like(pre_acts)
21 acts.scatter_(-1, topk_idx, topk_vals)
22 return acts
23
24# ── 3. Hook residual stream after the target transformer layer ────────────────
25captured = {}
26
27def _hook(module, input, output):
28 hidden = output[0] if isinstance(output, tuple) else output
29 captured["residual"] = hidden.detach().cpu()
30
31hook = model.model.layers[LAYER].register_forward_hook(_hook)
32
33# ── 4. Forward pass ───────────────────────────────────────────────────────────
34text = "The capital of France is"
35inputs = tokenizer(text, return_tensors="pt")
36with torch.no_grad():
37 model(**inputs)
38hook.remove()
39
40# ── 5. Extract feature activations ───────────────────────────────────────────
41residual = captured["residual"] # (1, seq_len, 4096)
42feature_acts = get_feature_acts(residual) # (1, seq_len, 65536)
43
44# Inspect active features for the last token
45last_token_acts = feature_acts[0, -1] # (65536,)
46active_idx = last_token_acts.nonzero(as_tuple=True)[0]
47print(f"Active features : {active_idx.tolist()}")
48print(f"Feature values : {last_token_acts[active_idx].tolist()}")app.py. You can run it locally:python app.py \
--model Qwen/Qwen3.5-9B \
--model-name-sae-trained-from qwen3.5-9b-base \
--model-name-analyzing-now qwen3.5-9b \
--sae-path Qwen/SAE-Res-Qwen3.5-9B-Base-W64K-L0_50 \
--top-k 50 \
--num-layers 32 \
--sae-width 65536 \
--d-model 4096 \
--server-port 78601@misc{qwen_scope,
2 title = {{Qwen-Scope}: Turning Sparse Features into Development Tools for Large Language Models},
3 url = {https://qianwen-res.oss-accelerate.aliyuncs.com/qwen-scope/Qwen_Scope.pdf},
4 author = {{Qwen Team}},
5 month = {April},
6 year = {2026}
7}