AbstractPhil commited on
Commit
8f831c4
·
verified ·
1 Parent(s): 060689c

exp008 shipped: multiband mechanism certifies (3/3 surgical band lesions; LOW expert wins its band; uniform objective doesn't pay - roles enter exp009)

Browse files
README.md CHANGED
@@ -75,6 +75,7 @@ resolution) so gaps live in a narrow band — the paired design is load-bearing.
75
  | exp003_sigma_registers | register probe: **sigma is the ONLY live axis** — caption/type/cond all compress to ≤0; ordering prereg MISS with design consequences | **shipped (candidate, s0)** |
76
  | exp004_anima_relay | relays on the 2B DiT via diffusion-pipe (bf16 per dtype law) | staged |
77
  | exp005_sdxl_tree4a | the SDXL capacity battery (guidepost/scaffold/skeleton) | designed |
 
78
  | exp006_sd15core_relay | CORE EPRED certification: **relay beats frozen (−2.5%) and matched LoRA 2-for-2; grounding gained (+0.036) where LoRA traded it; gates GROW on the core** | **shipped (candidate, s0)** |
79
  | exp007_amoe_lora | AMoE v1 vs monolith falsifier: **falsifier fires — uniform pressure ⇒ flat usage, dispatch pays nothing (Tree-1b law on diffusion); machinery green; next = structural band assignment** | **shipped (candidate, s0)** |
80
 
 
75
  | exp003_sigma_registers | register probe: **sigma is the ONLY live axis** — caption/type/cond all compress to ≤0; ordering prereg MISS with design consequences | **shipped (candidate, s0)** |
76
  | exp004_anima_relay | relays on the 2B DiT via diffusion-pipe (bf16 per dtype law) | staged |
77
  | exp005_sdxl_tree4a | the SDXL capacity battery (guidepost/scaffold/skeleton) | designed |
78
+ | exp008_multiband | band-ASSIGNED experts: **mechanism certifies — 3/3 surgical band lesions (50-200x), LOW-noise expert wins its band; uniform objective doesn't pay (roles enter exp009)** | **shipped (candidate, s0; s1 running)** |
79
  | exp006_sd15core_relay | CORE EPRED certification: **relay beats frozen (−2.5%) and matched LoRA 2-for-2; grounding gained (+0.036) where LoRA traded it; gates GROW on the core** | **shipped (candidate, s0)** |
80
  | exp007_amoe_lora | AMoE v1 vs monolith falsifier: **falsifier fires — uniform pressure ⇒ flat usage, dispatch pays nothing (Tree-1b law on diffusion); machinery green; next = structural band assignment** | **shipped (candidate, s0)** |
81
 
exp008_multiband/README.md ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # exp008_multiband — band-assignment mechanism test (CANDIDATE, s0; s1 running)
2
+
3
+ **Question.** Do sigma-band-ASSIGNED experts (structural cosine-crossfade
4
+ windows, no selection event) become genuine band specialists, and does the
5
+ partition beat a matched monolith? First bed of the multiband stepwise stage
6
+ (stage plan: coarse-to-fine band roles — HIGH diversity/blobbing, MID
7
+ continuity/semantics, LOW fidelity/detail; roles enter as objectives in
8
+ exp009 — this bed certifies the MECHANISM under a uniform objective).
9
+
10
+ **Structure per site (16).** Three rank-16 zero-init deltas (W+b, gates
11
+ −3.0), combined by smooth cosine crossfade windows on s01 = t/1000 (edges
12
+ 0.35/0.75, half-width 0.06, sum-to-1 everywhere — positional gating, never
13
+ comparative). Per-band gradients arise from the windows. Falsifier: matched
14
+ rank-48 monolith (param ratio 1.021). Core epred substrate (2-seed
15
+ certified), shared dexp006 cache, 3000 steps, pure Adam wd=0.
16
+
17
+ **Results** (`results.json`):
18
+
19
+ | arm | overall val | band0 (HIGH) | band1 (MID) | band2 (LOW) |
20
+ |---|---|---|---|---|
21
+ | frozen | 0.124788 | 0.256406 | 0.064227 | 0.008726 |
22
+ | multiband3 | 0.122004 | 0.250432 | 0.063046 | **0.008534** |
23
+ | monolith r48 | **0.121736** | **0.249881** | **0.062896** | 0.008539 |
24
+
25
+ | prereg | outcome |
26
+ |---|---|
27
+ | P1 multiband ≥ monolith overall | MISS (monolith by 0.0003) |
28
+ | P2 own-band wins | 1/3 — the LOW-noise expert wins its band |
29
+ | P3 toggle bit-exact | HIT |
30
+ | **P4 band lesions surgical** | **HIT 3/3** — own-band damage 50–200× cross-band (band0 0.0059 vs 0.00003; band1 0.0010 vs 0.000014; band2 0.00016 vs 0.000003) |
31
+
32
+ **Verdict.** THE MECHANISM CERTIFIES: band assignment produces genuine,
33
+ surgically-decoupled band specialists (P4 — the sigma-axis analogue of the
34
+ program's double-dissociation batteries), and the toggle/parity laws hold.
35
+ Under a UNIFORM objective the partition does not yet out-earn shared capacity
36
+ (P1/P2) — consistent with exp007 (2-seed) and the text line's Law 1: the
37
+ payer must be differentiated pressure, not architecture alone. The one
38
+ per-band win is the LOW/fine-detail expert — the first data point for the
39
+ stage's "higher-fidelity distilled expert on low noise" thesis. Measured
40
+ band difficulty spans 30× (0.256/0.064/0.0087) — coarse-to-fine is intrinsic
41
+ to the objective.
42
+
43
+ **Next (per the stage plan).** exp009 attaches ROLE objectives per band
44
+ (LOW: high-frequency-weighted loss; HIGH: coarse-structure weighting; MID:
45
+ standard) on this certified mechanism; exp010 mounts the step-gated
46
+ controller at inference with the generation-side lesion battery.
47
+
48
+ **Caveats.** s0 (s1 replicating now); uniform objective by design; one
49
+ substrate; band edges fixed at 0.35/0.75. Cost ≈ 2.8 GPU-h.
50
+ Checkpoints: `mb3_s0.pt`, `mono48_s0.pt`.
exp008_multiband/dexp008_multiband.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """dexp008_multiband.py — exp008: MULTIBAND STEPWISE AMoE, the band-assignment
2
+ mechanism test (stage plan: history/plans/2026-07-17_multiband_stage_plan.md).
3
+
4
+ Phil's band-role map (roles enter as OBJECTIVES in exp009; this bed certifies
5
+ the MECHANISM): HIGH (0.75,1] diversity/blobbing | MID (0.35,0.75]
6
+ continuity/semantics | LOW [0,0.35] fidelity/detail.
7
+
8
+ Per site (16): three rank-16 zero-init deltas (W+b, own gates -3.0), combined
9
+ by SMOOTH COSINE CROSSFADE WINDOWS on s01 (width 0.06, sum to 1 everywhere —
10
+ STRUCTURAL/positional gating, dense + differentiable, no selection event).
11
+ Per-band gradients arise from the windows themselves: a sample at s01=0.9
12
+ trains (almost) only the HIGH expert. Falsifier: matched monolith rank-48.
13
+
14
+ Prereg (stage plan):
15
+ P1 multiband >= monolith on overall paired val;
16
+ P2 SPECIALIZATION SIGNATURE — each band expert beats the monolith IN ITS
17
+ OWN band (per-band paired val);
18
+ P3 toggle bit-exact post-train;
19
+ P4 BAND LESION — disabling band-b's experts damages band-b val >> other
20
+ bands (surgical decoupling on the sigma axis).
21
+ Substrate: core epred SD1.5 (2-seed certified). Reuses the dexp006 cache.
22
+
23
+ Pod: bash pod2/run_exp008.sh [DEXP8_SEED=0 DEXP8_STEPS=3000]
24
+ """
25
+ from __future__ import annotations
26
+
27
+ import json
28
+ import math
29
+ import os
30
+ import sys
31
+ import time
32
+
33
+ sys.path[:0] = ["pod2", "."]
34
+
35
+ import torch
36
+ import torch.nn as nn
37
+ import torch.nn.functional as F
38
+
39
+ from pod_ledger import ledger_run, note, burn_down
40
+ from d1_substrate import enumerate_sd15_sites, MEM_FRACTION
41
+ from dexp006_sd15core_relay import make_schedule, add_noise
42
+
43
+ SD_BASE = "stable-diffusion-v1-5/stable-diffusion-v1-5"
44
+ N_TRAIN, N_VAL = 4096, 256
45
+ RANK, N_BANDS = 16, 3
46
+ BAND_EDGES = (0.35, 0.75) # LOW [0,.35] | MID (.35,.75] | HIGH (.75,1]
47
+ XFADE = 0.06 # cosine crossfade half-width
48
+ BATCH = int(os.environ.get("DEXP8_BATCH", "16"))
49
+ STEPS = int(os.environ.get("DEXP8_STEPS", "3000"))
50
+ SEED = int(os.environ.get("DEXP8_SEED", "0"))
51
+ LR, CFG_DROPOUT = 1e-3, 0.1
52
+ DATA_DIR = ("/workspace/data/dexp008" if os.path.isdir("/workspace")
53
+ else os.path.join(os.environ.get("GEOLIP_DATA", "./data"),
54
+ "dexp008"))
55
+ DEXP6_DIR = ("/workspace/data/dexp006" if os.path.isdir("/workspace")
56
+ else os.path.join(os.environ.get("GEOLIP_DATA", "./data"),
57
+ "dexp006"))
58
+ CKPT_DIR = ("/workspace/ckpts2/dexp008" if os.path.isdir("/workspace")
59
+ else DATA_DIR)
60
+
61
+
62
+ def band_weights(s01: torch.Tensor) -> torch.Tensor:
63
+ """Smooth structural band windows: (B, 3), sum to 1 everywhere.
64
+ Cosine crossfade of half-width XFADE around each edge — positional
65
+ gating on the sigma axis, never comparative."""
66
+ def ramp(x): # 0 below -XFADE, 1 above +XFADE, smooth
67
+ t = ((x / XFADE).clamp(-1, 1) + 1) / 2
68
+ return 0.5 - 0.5 * torch.cos(t * math.pi)
69
+ e1, e2 = BAND_EDGES
70
+ up1, up2 = ramp(s01 - e1), ramp(s01 - e2)
71
+ low = 1 - up1
72
+ mid = up1 * (1 - up2)
73
+ high = up1 * up2
74
+ return torch.stack([low, mid, high], dim=-1)
75
+
76
+
77
+ def band_of(s01: float) -> int:
78
+ e1, e2 = BAND_EDGES
79
+ return 0 if s01 <= e1 else (1 if s01 <= e2 else 2)
80
+
81
+
82
+ class MultibandDelta(nn.Module):
83
+ """Three band experts per site, window-combined; per-expert enable flags
84
+ (band lesions) + global enable (toggle law)."""
85
+
86
+ def __init__(self, d: int, r: int = RANK):
87
+ super().__init__()
88
+ self.d, self.r = d, r
89
+ self.down = nn.ModuleList(nn.Linear(d, r, bias=False)
90
+ for _ in range(N_BANDS))
91
+ self.up = nn.ModuleList(nn.Linear(r, d) for _ in range(N_BANDS))
92
+ for dn, up in zip(self.down, self.up):
93
+ nn.init.orthogonal_(dn.weight)
94
+ nn.init.zeros_(up.weight)
95
+ nn.init.zeros_(up.bias)
96
+ self.gates = nn.Parameter(torch.full((N_BANDS,), -3.0))
97
+ self.enabled = True
98
+ self.band_enabled = [True] * N_BANDS
99
+
100
+ def assert_zero_init(self):
101
+ for up in self.up:
102
+ assert up.weight.abs().max().item() == 0.0
103
+ assert up.bias.abs().max().item() == 0.0
104
+
105
+ def forward(self, x, w_bands): # w_bands: (B, 3)
106
+ if not self.enabled:
107
+ return x
108
+ g = torch.sigmoid(self.gates)
109
+ delta = 0
110
+ w = w_bands.view(w_bands.shape[0],
111
+ *([1] * (x.ndim - 2)), N_BANDS)
112
+ for b in range(N_BANDS):
113
+ if not self.band_enabled[b]:
114
+ continue
115
+ delta = delta + g[b] * w[..., b:b + 1] * self.up[b](
116
+ self.down[b](x))
117
+ return x + delta if not isinstance(delta, int) else x
118
+
119
+
120
+ class MonoDelta(nn.Module):
121
+ def __init__(self, d: int, r: int = RANK * N_BANDS):
122
+ super().__init__()
123
+ self.down = nn.Linear(d, r, bias=False)
124
+ nn.init.orthogonal_(self.down.weight)
125
+ self.up = nn.Linear(r, d)
126
+ nn.init.zeros_(self.up.weight)
127
+ nn.init.zeros_(self.up.bias)
128
+ self.gate = nn.Parameter(torch.tensor(-3.0))
129
+ self.enabled = True
130
+
131
+ def forward(self, x, w_bands=None):
132
+ if not self.enabled:
133
+ return x
134
+ return x + torch.sigmoid(self.gate) * self.up(self.down(x))
135
+
136
+
137
+ class BlockWrap(nn.Module):
138
+ def __init__(self, block, mod):
139
+ super().__init__()
140
+ self.block = block
141
+ self.mod = mod
142
+ self.w_bands = None
143
+
144
+ def forward(self, *args, **kwargs):
145
+ out = self.block(*args, **kwargs)
146
+ h = out[0] if isinstance(out, tuple) else out
147
+ h = self.mod(h, self.w_bands)
148
+ return (h,) + out[1:] if isinstance(out, tuple) else h
149
+
150
+
151
+ def load_unet(device):
152
+ from diffusers import UNet2DConditionModel
153
+ unet = UNet2DConditionModel.from_pretrained(
154
+ SD_BASE, subfolder="unet", torch_dtype=torch.float32).to(device)
155
+ unet.requires_grad_(False)
156
+ unet.eval()
157
+ unet.enable_gradient_checkpointing()
158
+ return unet
159
+
160
+
161
+ def attach(unet, mk):
162
+ sites = enumerate_sd15_sites(unet)
163
+ assert len(sites) == 16
164
+ mods, wraps = nn.ModuleList(), []
165
+ for name, block, d in sites:
166
+ p0 = next(block.parameters())
167
+ m = mk(d).to(device=p0.device, dtype=p0.dtype)
168
+ w = BlockWrap(block, m)
169
+ parent = unet
170
+ parts = name.split(".")
171
+ for p in parts[:-1]:
172
+ parent = getattr(parent, p) if not p.isdigit() else parent[int(p)]
173
+ if parts[-1].isdigit():
174
+ parent[int(parts[-1])] = w
175
+ else:
176
+ setattr(parent, parts[-1], w)
177
+ mods.append(m)
178
+ wraps.append(w)
179
+ return mods, wraps
180
+
181
+
182
+ def run(device="cuda"):
183
+ torch.cuda.set_per_process_memory_fraction(MEM_FRACTION, 0)
184
+ os.makedirs(CKPT_DIR, exist_ok=True)
185
+ os.makedirs(DATA_DIR, exist_ok=True)
186
+ acp = make_schedule(device)
187
+ cache_f = os.path.join(DEXP6_DIR, "cache.pt")
188
+ assert os.path.exists(cache_f), "needs the dexp006 cache"
189
+ cache = torch.load(cache_f, map_location="cpu", weights_only=True)
190
+
191
+ def set_w(wraps, s01):
192
+ w = band_weights(s01)
193
+ for wr in wraps:
194
+ wr.w_bands = w
195
+
196
+ def loss_of(unet, wraps, lat, ehs, gen):
197
+ bsz = lat.shape[0]
198
+ drop = torch.rand(bsz, generator=gen, device=device) < CFG_DROPOUT
199
+ ehs = ehs.clone()
200
+ ehs[drop] = 0
201
+ t = torch.randint(0, 1000, (bsz,), generator=gen, device=device)
202
+ set_w(wraps, t.float() / 1000.0)
203
+ noise = torch.randn(lat.shape, generator=gen, device=device)
204
+ pred = unet(add_noise(lat, noise, t, acp), t, ehs,
205
+ return_dict=False)[0]
206
+ return F.mse_loss(pred, noise)
207
+
208
+ @torch.no_grad()
209
+ def val(unet, wraps):
210
+ tot, per_band = [], {0: [], 1: [], 2: []}
211
+ for i in range(0, N_VAL, 32):
212
+ lat = cache["val_lat"][i:i + 32].to(device)
213
+ ehs = cache["val_ehs"][i:i + 32].to(device)
214
+ noise = cache["val_noise"][i:i + 32].to(device)
215
+ t = cache["val_t"][i:i + 32].to(device)
216
+ set_w(wraps, t.float() / 1000.0)
217
+ pred = unet(add_noise(lat, noise, t, acp), t, ehs,
218
+ return_dict=False)[0]
219
+ mse = ((pred - noise) ** 2).mean(dim=(1, 2, 3))
220
+ tot += mse.tolist()
221
+ for j, tv in enumerate((t.float() / 1000.0).tolist()):
222
+ per_band[band_of(tv)].append(mse[j].item())
223
+ return (sum(tot) / len(tot),
224
+ {f"band{b}": round(sum(v) / max(len(v), 1), 6)
225
+ for b, v in per_band.items()},
226
+ {f"band{b}_n": len(v) for b, v in per_band.items()})
227
+
228
+ def train(unet, wraps, params, label):
229
+ opt = torch.optim.Adam(params, lr=LR, weight_decay=0.0)
230
+ gen = torch.Generator(device=device).manual_seed(SEED + 42)
231
+ idx = torch.Generator().manual_seed(SEED + 7)
232
+ torch.cuda.reset_peak_memory_stats()
233
+ t0 = time.time()
234
+ for step in range(1, STEPS + 1):
235
+ sel = torch.randint(0, N_TRAIN, (BATCH,), generator=idx)
236
+ loss = loss_of(unet, wraps, cache["lat"][sel].to(device),
237
+ cache["ehs"][sel].to(device), gen)
238
+ loss.backward()
239
+ opt.step()
240
+ opt.zero_grad(set_to_none=True)
241
+ if step == 50 or step % 500 == 0:
242
+ print(f"[{label}] step {step}: loss {loss.item():.4f} | "
243
+ f"{(time.time() - t0) / step:.2f}s/step | peak "
244
+ f"{torch.cuda.max_memory_allocated() / 2**30:.1f}GB",
245
+ flush=True)
246
+ return round((time.time() - t0) / STEPS, 3)
247
+
248
+ results = {"config": {"bands": 3, "edges": BAND_EDGES, "xfade": XFADE,
249
+ "rank": RANK, "steps": STEPS, "batch": BATCH,
250
+ "lr": LR, "seed": SEED, "substrate": "core epred"}}
251
+
252
+ with ledger_run(f"dexp008 frozen s{SEED}", budget_h=0.2) as h:
253
+ unet = load_unet(device)
254
+ v, pb, pn = val(unet, [])
255
+ results["frozen"] = {"val": v, "per_band": pb, "band_n": pn}
256
+ del unet
257
+ torch.cuda.empty_cache()
258
+ h["verdict"] = f"val {v:.5f}"
259
+
260
+ with ledger_run(f"dexp008 multiband3 s{SEED}", budget_h=2.5) as h:
261
+ unet = load_unet(device)
262
+ mods, wraps = attach(unet, lambda d: MultibandDelta(d))
263
+ for m in mods:
264
+ m.assert_zero_init()
265
+ n_params = sum(p.numel() for p in mods.parameters())
266
+ print(f"[mb3] 16 sites x 3 band experts, {n_params:,} trainable",
267
+ flush=True)
268
+ spd = train(unet, wraps, mods.parameters(), "mb3")
269
+ v_on, pb_on, _ = val(unet, wraps)
270
+ for m in mods: # P3 toggle
271
+ m.enabled = False
272
+ v_off, _, _ = val(unet, wraps)
273
+ d = abs(v_off - results["frozen"]["val"])
274
+ assert d < 1e-9, f"toggle parity broken: {d}"
275
+ for m in mods:
276
+ m.enabled = True
277
+ # P4 band lesions: disable band b everywhere, re-val per band
278
+ lesions = {}
279
+ for b in range(N_BANDS):
280
+ for m in mods:
281
+ m.band_enabled[b] = False
282
+ _, pb_les, _ = val(unet, wraps)
283
+ lesions[f"lesion_band{b}"] = pb_les
284
+ for m in mods:
285
+ m.band_enabled[b] = True
286
+ torch.save({"mods": [m.state_dict() for m in mods]},
287
+ os.path.join(CKPT_DIR, f"mb3_s{SEED}.pt"))
288
+ results["multiband3"] = {
289
+ "n_params": n_params, "val": v_on, "per_band": pb_on,
290
+ "val_toggled_off": v_off, "s_per_step": spd,
291
+ "lesions": lesions,
292
+ "gates": [[round(torch.sigmoid(g).item(), 4)
293
+ for g in m.gates] for m in mods[8:9]][0]}
294
+ del unet, mods
295
+ torch.cuda.empty_cache()
296
+ h["verdict"] = f"val {v_on:.5f}"
297
+
298
+ with ledger_run(f"dexp008 monolith r48 s{SEED}", budget_h=2.5) as h:
299
+ unet = load_unet(device)
300
+ mods, wraps = attach(unet, lambda d: MonoDelta(d))
301
+ n_params = sum(p.numel() for p in mods.parameters())
302
+ print(f"[mono48] {n_params:,} trainable", flush=True)
303
+ spd = train(unet, wraps, mods.parameters(), "mono48")
304
+ v, pb, _ = val(unet, wraps)
305
+ torch.save({"mods": [m.state_dict() for m in mods]},
306
+ os.path.join(CKPT_DIR, f"mono48_s{SEED}.pt"))
307
+ results["monolith"] = {"n_params": n_params, "val": v,
308
+ "per_band": pb, "s_per_step": spd}
309
+ del unet, mods
310
+ torch.cuda.empty_cache()
311
+ h["verdict"] = f"val {v:.5f}"
312
+
313
+ mb, mo = results["multiband3"], results["monolith"]
314
+ per_band_wins = {b: mb["per_band"][b] < mo["per_band"][b]
315
+ for b in ("band0", "band1", "band2")}
316
+ lesion_asym = {}
317
+ for b in range(N_BANDS):
318
+ les = mb["lesions"][f"lesion_band{b}"]
319
+ own = les[f"band{b}"] - mb["per_band"][f"band{b}"]
320
+ other = sum(les[f"band{o}"] - mb["per_band"][f"band{o}"]
321
+ for o in range(N_BANDS) if o != b) / (N_BANDS - 1)
322
+ lesion_asym[f"band{b}"] = {"own_damage": round(own, 6),
323
+ "other_damage": round(other, 6),
324
+ "surgical": own > 3 * abs(other) and own > 0}
325
+ results["verdict"] = {
326
+ "P1_multiband_vs_monolith": "multiband" if mb["val"] <= mo["val"]
327
+ else "monolith",
328
+ "P2_per_band_wins": per_band_wins,
329
+ "P4_lesion_asymmetry": lesion_asym,
330
+ "param_ratio": round(mb["n_params"] / mo["n_params"], 3),
331
+ "note": f"seed {SEED}; mechanism test — roles enter in exp009",
332
+ }
333
+ with open(os.path.join(DATA_DIR, "results.json" if SEED == 0
334
+ else f"results_s{SEED}.json"), "w") as f:
335
+ json.dump(results, f, indent=2)
336
+ note(f"dexp008 verdict: {json.dumps(results['verdict'])}")
337
+ print(json.dumps(results["verdict"], indent=2))
338
+ burn_down()
339
+ return results
340
+
341
+
342
+ def smoke():
343
+ w = band_weights(torch.tensor([0.1, 0.35, 0.55, 0.75, 0.9, 0.72, 0.78]))
344
+ assert w.shape == (7, 3)
345
+ assert torch.allclose(w.sum(-1), torch.ones(7), atol=1e-6), "windows must sum to 1"
346
+ assert w[0].argmax() == 0 and w[2].argmax() == 1 and w[4].argmax() == 2
347
+ m = MultibandDelta(320)
348
+ m.assert_zero_init()
349
+ x = torch.randn(2, 9, 320)
350
+ wb = band_weights(torch.tensor([0.2, 0.9]))
351
+ assert torch.equal(m(x, wb), x), "zero-init must be exact"
352
+ m.enabled = False
353
+ assert m(x, wb) is x
354
+ m.enabled = True
355
+ m.band_enabled = [False, False, False]
356
+ assert m(x, wb) is x, "all-band lesion must be code-path exact"
357
+ m.band_enabled = [True] * 3
358
+ nn.init.normal_(m.up[0].weight, std=0.02)
359
+ assert not torch.equal(m(x, wb), x)
360
+ mb = sum(p.numel() for p in MultibandDelta(320).parameters())
361
+ mo = sum(p.numel() for p in MonoDelta(320).parameters())
362
+ print(f"dexp008 smoke PASSED (windows sum-1 + band argmax, zero-init, "
363
+ f"toggle, lesion path; params mb {mb:,} vs mono {mo:,} @d=320)")
364
+
365
+
366
+ if __name__ == "__main__":
367
+ if "--run" in sys.argv:
368
+ run()
369
+ else:
370
+ smoke()
exp008_multiband/mb3_s0.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9537d2ae03e90ac8aa9fe559be1dc882660d5a47ef04f7f5683d788427b06ae1
3
+ size 4988505
exp008_multiband/results.json ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "config": {
3
+ "bands": 3,
4
+ "edges": [
5
+ 0.35,
6
+ 0.75
7
+ ],
8
+ "xfade": 0.06,
9
+ "rank": 16,
10
+ "steps": 3000,
11
+ "batch": 16,
12
+ "lr": 0.001,
13
+ "seed": 0,
14
+ "substrate": "core epred"
15
+ },
16
+ "frozen": {
17
+ "val": 0.1247876692286809,
18
+ "per_band": {
19
+ "band0": 0.256406,
20
+ "band1": 0.064227,
21
+ "band2": 0.008726
22
+ },
23
+ "band_n": {
24
+ "band0_n": 98,
25
+ "band1_n": 98,
26
+ "band2_n": 60
27
+ }
28
+ },
29
+ "multiband3": {
30
+ "n_params": 1235568,
31
+ "val": 0.12200367445166194,
32
+ "per_band": {
33
+ "band0": 0.250432,
34
+ "band1": 0.063046,
35
+ "band2": 0.008534
36
+ },
37
+ "val_toggled_off": 0.1247876692286809,
38
+ "s_per_step": 1.685,
39
+ "lesions": {
40
+ "lesion_band0": {
41
+ "band0": 0.256343,
42
+ "band1": 0.063105,
43
+ "band2": 0.008534
44
+ },
45
+ "lesion_band1": {
46
+ "band0": 0.250449,
47
+ "band1": 0.06408,
48
+ "band2": 0.008546
49
+ },
50
+ "lesion_band2": {
51
+ "band0": 0.250432,
52
+ "band1": 0.063052,
53
+ "band2": 0.008691
54
+ }
55
+ },
56
+ "gates": [
57
+ 0.069,
58
+ 0.0608,
59
+ 0.0583
60
+ ]
61
+ },
62
+ "monolith": {
63
+ "n_params": 1210576,
64
+ "val": 0.12173647676991095,
65
+ "per_band": {
66
+ "band0": 0.249881,
67
+ "band1": 0.062896,
68
+ "band2": 0.008539
69
+ },
70
+ "s_per_step": 1.65
71
+ },
72
+ "verdict": {
73
+ "P1_multiband_vs_monolith": "monolith",
74
+ "P2_per_band_wins": {
75
+ "band0": false,
76
+ "band1": false,
77
+ "band2": true
78
+ },
79
+ "P4_lesion_asymmetry": {
80
+ "band0": {
81
+ "own_damage": 0.005911,
82
+ "other_damage": 2.9e-05,
83
+ "surgical": true
84
+ },
85
+ "band1": {
86
+ "own_damage": 0.001034,
87
+ "other_damage": 1.4e-05,
88
+ "surgical": true
89
+ },
90
+ "band2": {
91
+ "own_damage": 0.000157,
92
+ "other_damage": 3e-06,
93
+ "surgical": true
94
+ }
95
+ },
96
+ "param_ratio": 1.021,
97
+ "note": "seed 0; mechanism test \u2014 roles enter in exp009"
98
+ }
99
+ }