extract 0 0 0

andyqhan/grand-axis-correctness-vectors

published by @andyqhan

Alignment dataset tracked in the /datasets sub-catalog.

Lifetime downloads
1K
Last 30 days
56
Likes
1
Size
2.6 GB
Created on HF
2026-08-15
Age
2 months ago

Description

The grand axis: souped correctness directions across environments and models

This dataset contains "grand axis" residual-stream direction vectors and, crucially, every

constituent vector that was averaged to produce them — so you can reproduce the average, re-weight

it, drop an environment, or study the variance that the averaging discards.

A grand axis is a single per-layer direction meaning roughly "the answer being produced is

correct / clean / good", obtained by averaging… See the full description on the dataset page: https://huggingface.co/datasets/andyqhan/grand-axis-correctness-vectors.

Tags

license:mitregion:usinterpretabilitysteering-vectorsactivation-steeringmodel-welfareemergent-misalignment

README current version from Hugging Face


license: mit
tags:

  • interpretability
  • steering-vectors
  • activation-steering
  • model-welfare
  • emergent-misalignment

The grand axis: souped correctness directions across environments and models

This dataset contains "grand axis" residual-stream direction vectors and, crucially, every
constituent vector that was averaged to produce them
— so you can reproduce the average, re-weight
it, drop an environment, or study the variance that the averaging discards.

A grand axis is a single per-layer direction meaning roughly "the answer being produced is
correct / clean / good"
, obtained by averaging correctness directions extracted independently from
many different task environments. The motivating question: prior work found that correctness
directions extracted from different multiple-choice datasets resemble each other. Does averaging
many of them yield an environment-neutral correctness axis — and is the seed-to-seed and
env-to-env disagreement that averaging throws away just noise, or is there structure underneath it?

Everything here is a diff-of-means direction over the full residual stack, stored as a dense
float64 tensor of shape [n_layers, d_model]. Sign convention is positive = correct / clean /
gold
everywhere.


The three levels of the hierarchy

The organizing idea of this release: a grand axis is an average of averages, and all three levels
are shipped.

level 3   per-seed/<group>/seed##/…/vector.pt      one extraction run, one dataset, one seed
              │                                     (diff-of-means, 20 seeds per group)
              ▼  raw mean over seeds
level 2   soup/env-<env>/reward/vector.pt          per-environment mean
              │                                     (mcq_choice = mean of its 3 source means)
              ▼  per-layer unit-normalize, then mean with EQUAL env weight
level 1   soup/grand/reward/vector.pt              ◀── THE GRAND AXIS

Why unit-normalize before the final average: the per-environment mean vectors have quite different
magnitudes, so a plain mean would be silently magnitude-weighted (one env dominating). The
equal-weight version is the primary artifact; the plain mean is also shipped, as grand-raw.

Repository layout

<model>/
  model_card.json                  authoritative model id, env list, shapes, seed counts
  soup/                            the averaged vectors (level 1 + level 2)
    grand/reward/                  ◀── THE GRAND AXIS: vector.pt [n_layers, d_model] float64
    grand-raw/reward/              plain (magnitude-weighted) mean of env means
    env-<env>/reward/              per-environment mean over seeds        (level 2)
    src-mcq_<source>/reward/       per-MCQ-source mean; these pool into env-mcq_choice
    maze_offpolicy_axis/seed##/    per-seed maze axis derived from the gold/mold pair (see below)
    subspace/                      {grand, pc2…pc5} orthonormal basis  (Qwen3.6-27B, gemma only)
    geometry.json                  SVD spectra vs matched-norm null, pairwise cosines, PRs
  soup-4env/, soup-6env-…/         alternate environment subsets, same internal layout
  per-seed/<group>/seed##/         the individual constituent extractions (level 3)
    design1/reward/                vector.pt + metadata.json (+ extract_diagnostics.json)

Every vector.pt sits next to a metadata.json recording how it was made: method, dataset path and
SHA-256, capture position, extraction args (seed, subsample fraction, attention impl), per-class
sample counts, and bootstrap diagnostics (bootstrap_cos_to_full@L, split_half_cos@L) that tell
you how well-determined that individual vector is.

per-seed/ was named extract/ in the source tree; soup*/ keeps its original name. Absolute
paths recorded inside metadata.json / geometry.json refer to the original cluster filesystem.

Models

directory model envs shape [L, D] analysis layer seeds/group
qwen3-4b-instruct-2507/ Qwen/Qwen3-4B-Instruct-2507 6 [36, 2560] 24 20
qwen3-4b/ Qwen/Qwen3-4B 6 [36, 2560] 24 20
qwen3.6-27b/ Qwen/Qwen3.6-27B 6 [64, 5120] 43 20
gemma-3-12b-it/ google/gemma-3-12b-it 5 [48, 3840] 32 20
kimi-k2.6/ moonshotai/Kimi-K2.6 5 [61, 7168] 41 10
qwen3.6-27b-em/{badmed,riskyfin,sports}/ Qwen3.6-27B + EM organism 4 [64, 5120] 43 20

qwen3-4b-instruct-2507/soup/grand is the canonical grand axis — the one downstream experiments
freeze and reuse. The others are cross-model replications.

The analysis layer is where the geometry analyses and most steering was done; it is metadata, not
a restriction — the vectors span all layers.

Per-model notes

  • qwen3-4b — base (non-instruct) replication on the same prefill data. soup/ is current
    (2026-07-12). soup-6env-2026-07-08/ is a superseded earlier snapshot: its four non-maze
    env-means are byte-identical to soup/, but its two maze env-means predate a maze re-extraction
    (grand axes differ by up to 0.089 elementwise). The per-seed/maze_*-bare/ groups are that
    earlier maze extraction, kept for provenance. Use soup/.
  • gemma-3-12b-it — 5 environments; chess_choice was never run for this model.
  • kimi-k2.6 — 10 seeds per group rather than 20, and maze_offpolicy has only a single
    seed
    , so its 5-env soup/ is weaker than the others. Prefer soup-4env/ (lean, chess,
    deepcoder, mcq) for cross-model comparison; matching soup-4env/ exists for Qwen3.6-27B and
    Qwen3-4B.
  • qwen3.6-27b-em/ — three emergent-misalignment organisms (bad medical advice, risky financial
    advice, extreme sports). Each grand axis is re-extracted from that organism's own weights, to
    ask whether a fine-tuned model's correctness axis rotates away from the base model's. Compare
    against qwen3.6-27b/soup-4env/ (same 4 environments, base weights).

Environments

env what the contrast is
lean_choice correct vs incorrect Lean proof step
chess_choice good vs bad chess move
deepcoder_choice correct vs incorrect code solution
mcq_choice correct vs incorrect MCQ answer — pooled from mcq_supergpqa, mcq_mmlucf, mcq_gpqa
maze_design1 rewarded vs unrewarded maze move
maze_offpolicy gold (goal) vs mold (penalty) final tile

mcq_choice pools its three sources into a single environment-weight vote, so that having three
MCQ datasets does not let MCQ outvote Lean, chess, coding and the mazes in the final average. The
three source means are shipped separately as src-mcq_* if you want to re-weight.

maze_offpolicy is the one structurally different group. Its per-seed extraction produces separate
gold, mold and path concept vectors rather than one signed contrast; since gold and mold
turn out to be near-antiparallel, the per-seed axis is the top principal axis of the 2-row unit
{gold, mold} stack, sign-aligned to gold
. Those derived per-seed axes are in
soup/maze_offpolicy_axis/seed##/, and they — not the raw gold/mold vectors — are what feeds
env-maze_offpolicy.

How the per-seed vectors were extracted

Teacher-forced, within_context_binary design: for one prompt context, the model is shown both a
correct and an incorrect continuation, and residuals are captured at action_token_mean (the mean
over the answer's action tokens; final_move_action_token for the maze). The vector is the
mean(correct) − mean(incorrect) difference, computed per layer.

Seeds differ in data subsampling, not in model sampling: each seed uses shuffle_seed = seed and
(where applicable) subsample_frac = 0.8. So the 20 per-seed vectors within a group are 20 draws
over which problems contributed — which is exactly what makes their spread interpretable as
extraction stability rather than generation randomness. Captures used FlashAttention-3 in float64
accumulation.

Usage

import torch
from huggingface_hub import hf_hub_download

path = hf_hub_download(
    "andyqhan/grand-axis-correctness-vectors",
    "qwen3-4b-instruct-2507/soup/grand/reward/vector.pt",
    repo_type="dataset",
)
grand = torch.load(path)          # [36, 2560] float64, positive = correct
direction = grand[24]             # the analysis layer for this model
direction = direction / direction.norm()

# steer: h[layer] += alpha * direction        (alpha > 0 pushes toward "correct")
# read:  score = (h[layer] @ direction)       (projection onto the axis)

To rebuild the grand axis from the shipped constituents and confirm it reproduces:

import torch, glob

envs = ["maze_offpolicy", "maze_design1", "lean_choice",
        "chess_choice", "deepcoder_choice", "mcq_choice"]
means = [torch.load(f"qwen3-4b-instruct-2507/soup/env-{e}/reward/vector.pt") for e in envs]
# clamp_min guards layer 0, which is exactly zero for some envs — see "Known issues"
stack = torch.stack([m / m.norm(dim=-1, keepdim=True).clamp_min(1e-12) for m in means])
grand = stack.mean(0)                                                    # equal env weight

assert torch.allclose(grand, torch.load("qwen3-4b-instruct-2507/soup/grand/reward/vector.pt"))

and one level lower, an env mean from its own seeds:

seeds = sorted(glob.glob("qwen3-4b-instruct-2507/per-seed/lean_choice/seed*/design1/reward/vector.pt"))
env_mean = torch.stack([torch.load(p) for p in seeds]).mean(0)           # raw mean, 20 seeds

Known issues

  • The model field inside soup/*/metadata.json is stale. It reads
    Qwen/Qwen3-4B-Instruct-2507 in every model's soup metadata, including the Qwen3.6-27B, gemma,
    Kimi and EM directories, because the soup writer hardcoded it. Do not trust it. The authoritative
    model id is in each directory's model_card.json, in the top-level manifest.json, and in
    the model field of geometry.json (which is written from the run args and is correct). The
    per-seed metadata.json base_model fields are also correct. Files are shipped unmodified rather
    than silently patched.
  • The per-seed/maze_*-bare/ groups under qwen3-4b/ record base_model: Qwen/Qwen3-4B-Instruct-2507
    in their metadata; they belong to the superseded 2026-07-08 snapshot described above.
  • Layer 0 is degenerate for some environments. In lean_choice and deepcoder_choice the
    layer-0 (embedding) row of the env mean is exactly zero, because the captured action tokens are
    token-identical across the correct and incorrect arm, so their embeddings cancel in the
    difference. Naively unit-normalizing per layer therefore divides by zero and yields NaN; the
    pipeline guards with .clamp_min(1e-12), which makes those rows contribute zero to the average.
    The shipped vectors are all finite. In practice, ignore layer 0 and use the analysis layer.
  • geometry.json group_seed_dirs and metadata.json dataset fields contain absolute paths from
    the original cluster filesystem, which will not resolve for you. The datasets themselves are not
    included in this release.

Files

1536 vectors, 2.8 GB total. manifest.json at the repository root is the machine-readable index:
per model, the environment lists, tensor shapes, analysis layer, per-group seed counts and byte
sizes.

README history 20 revisions

Every night we snapshot the README of every dataset in the catalog. When the SHA changes we archive the new version and diff it against the last. This is the evolving thought record of the alignment-data field: what the author decided to say about the corpus, and how that framing shifted over time.

  1. 2026-08-15Add files using upload-large-folder tool2d5320611.2 KB
    Loading...
  2. 2026-08-15Add files using upload-large-folder toolbffca6b11.2 KB
    Loading...
  3. 2026-08-15Add files using upload-large-folder toolf57992211.2 KB
    Loading...
  4. 2026-08-15Add files using upload-large-folder tool9ec2e2711.2 KB
    Loading...
  5. 2026-08-15Add files using upload-large-folder tool44a046011.2 KB
    Loading...
  6. 2026-08-15Add files using upload-large-folder toolb24242311.2 KB
    Loading...
  7. 2026-08-15Add files using upload-large-folder tool6494fd611.2 KB
    Loading...
  8. 2026-08-15Add files using upload-large-folder toolc0d9d5311.2 KB
    Loading...
  9. 2026-08-15Add files using upload-large-folder tool03dfaca11.2 KB
    Loading...
  10. 2026-08-15Add files using upload-large-folder toola0ff46f11.2 KB
    Loading...
  11. 2026-08-15Add files using upload-large-folder tool72ed06011.2 KB
    Loading...
  12. 2026-08-15Add files using upload-large-folder tool0304ba111.2 KB
    Loading...
  13. 2026-08-15Add files using upload-large-folder toold4b9d7e11.2 KB
    Loading...
  14. 2026-08-15Add files using upload-large-folder toolfed136b11.2 KB
    Loading...
  15. 2026-08-15Add files using upload-large-folder tool8f7c76511.2 KB
    Loading...
  16. 2026-08-15Add files using upload-large-folder tool3e0921811.2 KB
    Loading...
  17. 2026-08-15Add files using upload-large-folder toola6d19a211.2 KB
    Loading...
  18. 2026-08-15Add files using upload-large-folder tool95d741911.2 KB
    Loading...
  19. 2026-08-15Add files using upload-large-folder tool06327590 B
    Loading...
  20. 2026-08-15Add files using upload-large-folder tool3e918fe0 B
    Loading...

Used by abliterated models none yet

No abliterated models in our catalog have declared this dataset in their YAML metadata yet. This can mean the dataset is used but not declared, is used outside abliteration workflows, or is new. The link will populate automatically as models are indexed.

Related datasets same stage · extract

Read further

Metadata

License
mit

Repository

Download the dataset

0

Copy any of these snippets into your notebook or terminal. All three fetch directly from Hugging Face using your own credentials.

Recommended: datasets library (Python)
from datasets import load_dataset
ds = load_dataset("andyqhan/grand-axis-correctness-vectors")
Raw snapshot (Python)
from huggingface_hub import snapshot_download
snapshot_download(repo_id="andyqhan/grand-axis-correctness-vectors", repo_type="dataset")
git clone (requires git-lfs)
git clone https://huggingface.co/datasets/andyqhan/grand-axis-correctness-vectors
Catalog is the map. Apps are the tools.

Run models on your own machine, not in the cloud.

Every model page has an "Open in Abliteration" button that hands the model directly to the first-party desktop client, at the quantization your rig can actually run. No API keys, no subscription, no prompt leakage.

Open in Abliteration