Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,34 @@

## Unreleased

(nothing yet)
### Added

- **Per-block diagnostic floats on `BlockReport`** (closes the Phase 2
v1 deferral). `rank_ratio`, `post_A`, and `informative_metric` now
populate per block; `forge_mse` stays caller-provided, same as the
top-level CompressionReport's. Empty-block degenerate case leaves
diagnostics as `None`. 2 new tests; full suite 1079 → 1081.

### Documented (scope honesty)

- **`add-encoding-partition` is polygram-only.** An A/B experiment on
a real SAE (jbloom GPT-2 first 64 features) with sae-forge's full
`ForgePipeline.run_synthetic` measured: substrate cost reduces
**8-16×** under partition (validated), but `forge_faithfulness_kl`
is **identical** between uniform and partitioned compressions
(10.0484 in both runs). The polygram encoding-family choice does
not propagate through sae-forge's current forge path — sae-forge
reads W_dec from the safetensors and the partition doesn't change
W_dec. The proposal's projected forge-side payoff (10-30% KL lift)
is **unproven** and requires separate sae-forge work that is not
specified anywhere today.
- Artefacts: `runs/real_partition_experiment.py` (reproducible
against a fresh venv with the jbloom SAE cached) +
`runs/real_partition_experiment.json` (measurement output).
- This is a useful negative result, not a failure of the feature.
The partition still works as a polygram-Dictionary substrate cost
reducer + analyst diagnostic tool. Just don't expect the forge
to honour the encoding choice today.

## 0.14.0 — 2026-05-21

Expand Down
28 changes: 21 additions & 7 deletions polygram/compression/compressor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1231,10 +1231,13 @@ def _build_block_report(
if m in fid_to_local:
assignments[fid_to_local[m]] = local_cid

# Per-block scale_compression_ratio (analogous to the top-level
# helper but scoped to this block's W_dec slice + per-block
# clusters). The local plan has local-indexed clusters; rebuild
# one for the helper.
# Per-block diagnostics (Phase 2 enhancement — completes Phase 2
# v1's deferred per-block rank_ratio / post_A / informative_metric).
# Rebuild a local-indexed plan for the existing diagnostic helpers,
# which take a CompressionPlan + W_dec slice and operate by row.
rank_ratio: float | None = None
post_A: float | None = None
informative_metric_value = None
if block_clusters:
local_plan = CompressionPlan(
clusters=tuple(
Expand All @@ -1254,6 +1257,17 @@ def _build_block_report(
scale_ratio = _compute_scale_compression_ratio(
sub_source_w_dec, local_plan, sub_merged_norms
)
# rank_ratio scoped to the block's rewritten sub-W_dec — the
# block's cluster representatives' decoder rows. Same numerical-
# rank-vs-d_model semantic as the top-level metric.
rank_ratio = _compute_rank_ratio(sub_rewritten_w_dec, local_plan)
# post_A scoped to the block's source sub-W_dec.
post_A = _compute_post_A(sub_source_w_dec, local_plan)
# informative_metric derived from rank_ratio per the existing
# _informative_metric rule (post_A < 0.95, both 0.95-1.05,
# forge_mse > 1.05).
if rank_ratio is not None:
informative_metric_value = _informative_metric(rank_ratio)
else:
scale_ratio = 1.0

Expand All @@ -1268,10 +1282,10 @@ def _build_block_report(
n_clusters=n_clusters,
cluster_assignments=tuple(assignments),
scale_compression_ratio=scale_ratio,
rank_ratio=None, # Phase 2 v1: deferred
post_A=None, # Phase 2 v1: deferred
rank_ratio=rank_ratio,
post_A=post_A,
forge_mse=None,
informative_metric=None,
informative_metric=informative_metric_value,
)


Expand Down
54 changes: 54 additions & 0 deletions runs/partition_payoff_measurement.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"n_features": 32,
"d_model": 64,
"n_confirmed_pairs": 16,
"uniform": {
"encoding": "Rung5(n_amp_qubits=4)",
"n_features_kept": 16,
"n_clusters": 16,
"scale_compression_ratio": 0.49999999254941935,
"substrate_cost_kept_reps_slots": 2048,
"substrate_cost_full_input_slots": 4096,
"wall_ms": 106.94289207458496
},
"partition": {
"blocks": [
{
"block_id": "heavy",
"encoding": "Rung5({'n_amp_qubits': 4})",
"slot_cost": 128,
"n_features": 4,
"n_kept": 2,
"n_zeroed": 2,
"n_clusters": 2,
"scale_compression_ratio": 0.5,
"rank_ratio": 0.03125,
"post_A": -1.1920928244535389e-07,
"informative_metric": "post_A"
},
{
"block_id": "tail",
"encoding": "MPSRung1({})",
"slot_cost": 8,
"n_features": 28,
"n_kept": 14,
"n_zeroed": 14,
"n_clusters": 14,
"scale_compression_ratio": 0.4999999914850507,
"rank_ratio": 0.21875,
"post_A": -8.514949412230521e-09,
"informative_metric": "post_A"
}
],
"n_features_kept": 16,
"n_clusters": 16,
"scale_compression_ratio": 0.49999999254941935,
"substrate_cost_kept_reps_slots": 368,
"substrate_cost_full_input_slots": 736,
"wall_ms": 17.501115798950195
},
"reductions": {
"kept_reps": 5.565217391304348,
"full_input_sae": 5.565217391304348
}
}
74 changes: 74 additions & 0 deletions runs/real_partition_experiment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"sae_repo": "jbloom/GPT2-Small-SAEs-Reformatted",
"sae_file": "blocks.8.hook_resid_pre/sae_weights.safetensors",
"n_features": 64,
"d_model": 768,
"heavy_k": 4,
"confirmer": "DecoderGeometryConfirmer",
"threshold": 0.1,
"n_confirmed_pairs": 4,
"heaviness_score": "decoder_norm\u00b2 \u00d7 pair_count",
"top_k_heavy_fids": [
3,
19,
22,
42
],
"uniform": {
"encoding": "Rung5(n_amp_qubits=4)",
"n_features_kept": 4,
"n_features_zeroed": 4,
"n_clusters": 4,
"scale_compression_ratio": 0.49999797352125386,
"rank_ratio": 0.005208333333333333,
"substrate_kept_slots": 512,
"substrate_full_slots": 8192,
"wall_s": 0.09181714057922363,
"forge_faithfulness_kl": 10.0484037399292,
"forge_n_params": 124439808
},
"partition": {
"blocks": [
{
"block_id": "heavy",
"encoding": "Rung5({'n_amp_qubits': 4})",
"slot_cost": 128,
"n_features": 4,
"n_kept": 0,
"n_zeroed": 0,
"n_clusters": 0,
"scale_compression_ratio": 1.0,
"rank_ratio": null,
"post_A": null,
"informative_metric": null
},
{
"block_id": "tail",
"encoding": "MPSRung1({})",
"slot_cost": 8,
"n_features": 60,
"n_kept": 4,
"n_zeroed": 4,
"n_clusters": 4,
"scale_compression_ratio": 0.49999797352125386,
"rank_ratio": 0.005208333333333333,
"post_A": 8.940070594931626e-08,
"informative_metric": "post_A"
}
],
"n_features_kept": 4,
"n_features_zeroed": 4,
"n_clusters": 4,
"scale_compression_ratio": 0.49999797352125386,
"rank_ratio": 0.005208333333333333,
"substrate_kept_slots": 32,
"substrate_full_slots": 992,
"wall_s": 0.03039097785949707,
"forge_faithfulness_kl": 10.0484037399292,
"forge_n_params": 124439808
},
"substrate_reductions": {
"kept_reps": 16.0,
"full_input_sae": 8.258064516129032
}
}
Loading
Loading