AbstractPhil commited on
Commit
c5da886
·
verified ·
1 Parent(s): 7ceb6a0

exp010 shipped: StepGatedSampler + generation-side lesion battery (controller +0.089 grounding; coarse-to-fine confirmed by lesion ratios; diversity = open training goal)

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
  | exp009_bandroles | role objectives: **directional hit 4/4 but noise-adjacent — frequency reweighting too collinear; needs qualitatively different supervision + generation-side gauges (exp010)** | **shipped (2 seeds + rejudge)** |
79
  | exp008_multiband | band-ASSIGNED experts: **mechanism certifies — 3/3 surgical band lesions (50-200x), HIGH-noise band expert wins its band (label-corrected); uniform objective doesn't pay (roles enter exp009)** | **shipped (candidate, s0; s1 running)** |
80
  | 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)** |
 
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
+ | exp010_controller | **StepGatedSampler ships**: controller lifts grounding +0.089 over frozen; monotonic lesion ladder; HIGH lesion 14x LP-dominant (coarse-to-fine confirmed in image space); eps-trained HIGH band concentrates (diversity = open training goal) | **shipped (candidate)** |
79
  | exp009_bandroles | role objectives: **directional hit 4/4 but noise-adjacent — frequency reweighting too collinear; needs qualitatively different supervision + generation-side gauges (exp010)** | **shipped (2 seeds + rejudge)** |
80
  | exp008_multiband | band-ASSIGNED experts: **mechanism certifies — 3/3 surgical band lesions (50-200x), HIGH-noise band expert wins its band (label-corrected); uniform objective doesn't pay (roles enter exp009)** | **shipped (candidate, s0; s1 running)** |
81
  | 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)** |
exp010_controller/README.md ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # exp010_controller — THE STEP-GATED DIFFUSION CONTROLLER + generation-side
2
+ # band-lesion battery (CANDIDATE, 1-seed battery)
3
+
4
+ **The artifact.** `StepGatedSampler` — DDIM sampling where EVERY denoising
5
+ step sets the band crossfade windows from the current timestep, activating
6
+ the trained band experts coarse-to-fine across the trajectory. The stage's
7
+ controller, shipped as a usable module.
8
+
9
+ **The question.** exp009 showed per-step eps-MSE is nearly blind to band
10
+ behavior (0.05–0.2% moves). What do the bands do IN IMAGE SPACE? Battery:
11
+ exp008's 2-seed-confirmed mb3 stack; arms all_on / lesion each band / frozen;
12
+ paired seeds; judged by round-trip grounding, lesion-vs-all_on LP/HP
13
+ decomposition, and within-prompt diversity (6 prompts × 4 seeds).
14
+
15
+ **Results** (`results.json`):
16
+
17
+ | arm | grounding gap | diversity | LP-change vs all_on | HP-change |
18
+ |---|---|---|---|---|
19
+ | **all_on** | **+0.2135** | 0.196 | — | — |
20
+ | lesion band0 (LOW noise) | +0.1979 | 0.208 | 0.0036 | 0.0031 |
21
+ | lesion band1 (MID) | +0.1821 | 0.217 | 0.0184 | 0.0039 |
22
+ | lesion band2 (HIGH noise) | +0.1782 | 0.297 | **0.0727** | 0.0051 |
23
+ | frozen | +0.1247 | 0.332 | 0.0804 | 0.0052 |
24
+
25
+ **Findings.**
26
+ 1. **The controller lifts grounding +0.089 over frozen** (+0.1247 → +0.2135)
27
+ and every band lesion cuts it monotonically — all three bands carry
28
+ generation-relevant signal that eps-MSE could not see. The image-space
29
+ instrument was the right upgrade.
30
+ 2. **Coarse-to-fine confirmed by lesion signature ratios**: the HIGH-band
31
+ lesion is 14× LP-dominated (0.0727 LP vs 0.0051 HP — structure/layout),
32
+ the LOW-band lesion is ~1:1 detail-leaning (0.0036/0.0031), MID
33
+ intermediate. (Raw prereg G2b "LOW moves HP most in absolute terms"
34
+ missed — layout shift mechanically drags detail with it; the per-lesion
35
+ ratio is the honest read, disclosed.)
36
+ 3. **Diversity interpretation flip (G3 miss, informative):** the eps-trained
37
+ HIGH band CONCENTRATES generations toward the conditioning (its lesion
38
+ raises diversity 0.196 → 0.297; frozen is most "diverse" because least
39
+ grounded). A diversity-CARRYING high-noise expert remains a training-
40
+ objective goal (nothing here trained for diversity), not a refuted
41
+ property — the docket's diversity/blob supervision is the open path.
42
+
43
+ **Caveats.** 1-seed battery (one noise-seed bank, n=24 + 6×4 diversity
44
+ probe); one checkpoint (uniform-trained mb3_s0; the roles checkpoint runs
45
+ the same battery as an amendment); CLIP-L gauges. Cost ≈ 0.2 GPU-h.
exp010_controller/dexp010_controller.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """dexp010_controller.py — exp010: THE STEP-GATED DIFFUSION CONTROLLER at
2
+ inference + the generation-side band-lesion battery (the instrument upgrade).
3
+
4
+ The controller (stage plan phase 3): during sampling, each denoising step
5
+ sets the band windows from the CURRENT timestep — band experts activate
6
+ coarse-to-fine across the trajectory exactly as trained. This file ships the
7
+ controller as a usable module (StepGatedSampler) and judges what the bands DO
8
+ IN IMAGE SPACE, where per-step eps-MSE may be gauge-blind (exp009 verdict).
9
+
10
+ Arms (trained mb3 stack, exp008 s0): all_on | lesion_band0 (LOW-noise/detail)
11
+ | lesion_band1 (MID) | lesion_band2 (HIGH-noise/structure) | frozen.
12
+
13
+ Image-space gauges (deterministic, paired seeds):
14
+ G1 round-trip: CLIP-L cond-vs-shuffled per arm (does lesioning band b
15
+ change grounding?).
16
+ G2 structure-vs-detail decomposition of the lesion effect: for the SAME
17
+ (prompt, seed), LP-MSE(lesioned img, all_on img) = coarse-structure
18
+ change; HP-MSE = fine-detail change. PREREG: lesion_band2 (HIGH) moves
19
+ LP most (coarse/blob role); lesion_band0 (LOW) moves HP most (detail
20
+ role); band1 intermediate. This is the image-space test of the
21
+ coarse-to-fine thesis.
22
+ G3 within-prompt diversity: 6 prompts x 4 seeds, mean pairwise CLIP
23
+ distance per arm — PREREG: lesion_band2 reduces diversity (the HIGH
24
+ band's diversity role).
25
+
26
+ Pod: bash pod2/run_exp010.sh
27
+ """
28
+ from __future__ import annotations
29
+
30
+ import io
31
+ import json
32
+ import os
33
+ import sys
34
+
35
+ sys.path[:0] = ["pod2", "."]
36
+
37
+ import numpy as np
38
+ import torch
39
+ import torch.nn.functional as F
40
+
41
+ from pod_ledger import ledger_run, note, burn_down
42
+ from d1_substrate import MEM_FRACTION
43
+ from aleph_diffusion_core import derangement
44
+ from dexp008_multiband import (MultibandDelta, band_weights, attach,
45
+ load_unet, N_BANDS)
46
+
47
+ SD_BASE = "stable-diffusion-v1-5/stable-diffusion-v1-5"
48
+ DEXP8_CKPT = ("/workspace/ckpts2/dexp008" if os.path.isdir("/workspace")
49
+ else "./data/dexp008")
50
+ N_JUDGE, STEPS_GEN, GUIDANCE = 24, 30, 7.5
51
+ CKPT_FILE = os.environ.get("DEXP10_CKPT", "mb3_s0.pt")
52
+ CKPT_DIR_ENV = os.environ.get("DEXP10_CKPT_DIR", "")
53
+ TAG = os.environ.get("DEXP10_TAG", "mb3_s0")
54
+ N_DIV_PROMPTS, N_DIV_SEEDS = 6, 4
55
+ SEED = 1234
56
+ DATA_DIR = ("/workspace/data/dexp010" if os.path.isdir("/workspace")
57
+ else os.path.join(os.environ.get("GEOLIP_DATA", "./data"),
58
+ "dexp010"))
59
+
60
+
61
+ class StepGatedSampler:
62
+ """THE CONTROLLER: DDIM sampling with per-step band gating — each step
63
+ sets the crossfade windows from the current timestep, activating band
64
+ experts coarse-to-fine across the trajectory."""
65
+
66
+ def __init__(self, unet, wraps, device):
67
+ from diffusers import DDIMScheduler
68
+ self.unet, self.wraps, self.device = unet, wraps, device
69
+ self.sched = DDIMScheduler.from_pretrained(SD_BASE,
70
+ subfolder="scheduler")
71
+
72
+ @torch.no_grad()
73
+ def sample(self, ehs_cond, seed, steps=STEPS_GEN, guidance=GUIDANCE):
74
+ B = ehs_cond.shape[0]
75
+ self.sched.set_timesteps(steps, device=self.device)
76
+ g = torch.Generator(device=self.device).manual_seed(seed)
77
+ x = torch.randn(B, 4, 64, 64, generator=g, device=self.device)
78
+ x = x * self.sched.init_noise_sigma
79
+ ehs_in = torch.cat([ehs_cond, torch.zeros_like(ehs_cond)], dim=0)
80
+ for t in self.sched.timesteps:
81
+ s01 = torch.full((2 * B,), float(t) / 1000.0, device=self.device)
82
+ w = band_weights(s01)
83
+ for wr in self.wraps:
84
+ wr.w_bands = w # the step gate
85
+ xin = self.sched.scale_model_input(torch.cat([x, x]), t)
86
+ eps = self.unet(xin, t, ehs_in, return_dict=False)[0]
87
+ e_c, e_u = eps.chunk(2)
88
+ eps = e_u + guidance * (e_c - e_u)
89
+ x = self.sched.step(eps, t, x).prev_sample
90
+ return x
91
+
92
+
93
+ def hp_img(x):
94
+ return x - F.avg_pool2d(x, 3, stride=1, padding=1)
95
+
96
+
97
+ def lp_img(x):
98
+ return F.avg_pool2d(x, 7, stride=1, padding=3)
99
+
100
+
101
+ def run(device="cuda"):
102
+ torch.cuda.set_per_process_memory_fraction(MEM_FRACTION, 0)
103
+ os.makedirs(DATA_DIR, exist_ok=True)
104
+ from PIL import Image
105
+ from diffusers import AutoencoderKL
106
+ from transformers import (CLIPTextModel, CLIPTokenizer, CLIPModel,
107
+ CLIPProcessor)
108
+ from d1_exp000b_natural import load_rows, encode_nl77
109
+ from d1_exp000_baselines import judge_selftest
110
+
111
+ rows = load_rows(N_JUDGE)
112
+ prompts = [r["prompt"] for r in rows]
113
+ perm = derangement(N_JUDGE, seed=SEED)
114
+
115
+ tok = CLIPTokenizer.from_pretrained(SD_BASE, subfolder="tokenizer")
116
+ te = CLIPTextModel.from_pretrained(
117
+ SD_BASE, subfolder="text_encoder",
118
+ torch_dtype=torch.float32).to(device).eval()
119
+ vae = AutoencoderKL.from_pretrained(
120
+ SD_BASE, subfolder="vae", torch_dtype=torch.float32).to(device).eval()
121
+ clip = CLIPModel.from_pretrained(
122
+ "openai/clip-vit-large-patch14",
123
+ torch_dtype=torch.float32).to(device).eval()
124
+ cproc = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")
125
+ feat = judge_selftest(clip, cproc, device)
126
+ with torch.no_grad():
127
+ ehs_c = encode_nl77(prompts, tok, te, device)
128
+ ehs_s = encode_nl77([prompts[i] for i in perm.tolist()], tok, te,
129
+ device)
130
+ orig = torch.cat([
131
+ feat(Image.open(io.BytesIO(r["image_bytes"])).convert("RGB"))
132
+ for r in rows])
133
+
134
+ unet = load_unet(device)
135
+ mods, wraps = attach(unet, lambda d: MultibandDelta(d))
136
+ ck_dir = CKPT_DIR_ENV or DEXP8_CKPT
137
+ ck = torch.load(os.path.join(ck_dir, CKPT_FILE),
138
+ map_location="cpu", weights_only=True)
139
+ for m, sd in zip(mods, ck["mods"]):
140
+ m.load_state_dict(sd, strict=True)
141
+ sampler = StepGatedSampler(unet, wraps, device)
142
+
143
+ def set_arm(arm):
144
+ for m in mods:
145
+ m.enabled = arm != "frozen"
146
+ m.band_enabled = [True] * N_BANDS
147
+ if arm.startswith("lesion_band"):
148
+ m.band_enabled[int(arm[-1])] = False
149
+
150
+ @torch.no_grad()
151
+ def decode_imgs(lat):
152
+ img = vae.decode(lat / 0.18215).sample
153
+ return ((img / 2 + 0.5).clamp(0, 1))
154
+
155
+ arms = ["all_on", "lesion_band0", "lesion_band1", "lesion_band2",
156
+ "frozen"]
157
+ results = {"config": {"steps": STEPS_GEN, "guidance": GUIDANCE,
158
+ "seed": SEED, "ckpt": TAG,
159
+ "sampler": "DDIM step-gated"}}
160
+ gen_store = {}
161
+
162
+ with ledger_run("dexp010 controller battery", budget_h=1.5) as h:
163
+ for arm in arms:
164
+ set_arm(arm)
165
+ imgs_all, cos = [], []
166
+ for i in range(0, N_JUDGE, 6):
167
+ lat = sampler.sample(ehs_c[i:i + 6], seed=SEED + i)
168
+ px = decode_imgs(lat)
169
+ imgs_all.append(px.cpu())
170
+ pil = [Image.fromarray(
171
+ (p.permute(1, 2, 0).numpy() * 255).astype(np.uint8))
172
+ for p in px.cpu()]
173
+ f = torch.cat([feat(p) for p in pil])
174
+ cos += (f * orig[i:i + 6]).sum(-1).tolist()
175
+ cond_mean = sum(cos) / len(cos)
176
+ cos_s = []
177
+ for i in range(0, N_JUDGE, 6):
178
+ lat = sampler.sample(ehs_s[i:i + 6], seed=SEED + i)
179
+ px = decode_imgs(lat)
180
+ pil = [Image.fromarray(
181
+ (p.permute(1, 2, 0).numpy() * 255).astype(np.uint8))
182
+ for p in px.cpu()]
183
+ f = torch.cat([feat(p) for p in pil])
184
+ cos_s += (f * orig[i:i + 6]).sum(-1).tolist()
185
+ gen_store[arm] = torch.cat(imgs_all)
186
+ results[arm] = {
187
+ "round_trip": {"cond": round(cond_mean, 4),
188
+ "shuffled": round(sum(cos_s) / len(cos_s), 4),
189
+ "gap": round(cond_mean
190
+ - sum(cos_s) / len(cos_s), 4)}}
191
+ print(f"[exp010] {arm}: rt gap "
192
+ f"{results[arm]['round_trip']['gap']:+.4f}", flush=True)
193
+
194
+ # G2: structure-vs-detail decomposition of each lesion (vs all_on)
195
+ base_imgs = gen_store["all_on"]
196
+ for arm in ("lesion_band0", "lesion_band1", "lesion_band2",
197
+ "frozen"):
198
+ d = gen_store[arm] - base_imgs
199
+ results[arm]["vs_all_on"] = {
200
+ "lp_change": round(float((lp_img(gen_store[arm])
201
+ - lp_img(base_imgs)).pow(2).mean()),
202
+ 6),
203
+ "hp_change": round(float((hp_img(gen_store[arm])
204
+ - hp_img(base_imgs)).pow(2).mean()),
205
+ 6),
206
+ "total_change": round(float(d.pow(2).mean()), 6)}
207
+
208
+ # G3: within-prompt diversity (6 prompts x 4 seeds)
209
+ for arm in arms:
210
+ set_arm(arm)
211
+ div = []
212
+ for pi in range(N_DIV_PROMPTS):
213
+ fs = []
214
+ for si in range(N_DIV_SEEDS):
215
+ lat = sampler.sample(ehs_c[pi:pi + 1],
216
+ seed=SEED + 1000 + 97 * si)
217
+ px = decode_imgs(lat).cpu()[0]
218
+ pil = Image.fromarray(
219
+ (px.permute(1, 2, 0).numpy() * 255).astype(np.uint8))
220
+ fs.append(feat(pil))
221
+ fs = torch.cat(fs)
222
+ sim = fs @ fs.T
223
+ n = fs.shape[0]
224
+ div.append(1 - ((sim.sum() - n) / (n * (n - 1))).item())
225
+ results[arm]["diversity"] = round(sum(div) / len(div), 5)
226
+ h["verdict"] = json.dumps(
227
+ {a: results[a]["round_trip"]["gap"] for a in arms})
228
+
229
+ # prereg checks
230
+ lb0 = results["lesion_band0"]["vs_all_on"]
231
+ lb2 = results["lesion_band2"]["vs_all_on"]
232
+ results["prereg"] = {
233
+ "G2_high_band_moves_LP_most":
234
+ lb2["lp_change"] > lb0["lp_change"],
235
+ "G2_low_band_moves_HP_most":
236
+ lb0["hp_change"] > lb2["hp_change"],
237
+ "G3_high_lesion_cuts_diversity":
238
+ results["lesion_band2"]["diversity"]
239
+ < results["all_on"]["diversity"],
240
+ "note": "image-space coarse-to-fine test; 1-seed battery",
241
+ }
242
+ with open(os.path.join(DATA_DIR, "results.json" if TAG == "mb3_s0" else f"results_{TAG}.json"), "w") as f:
243
+ json.dump(results, f, indent=2)
244
+ note(f"dexp010: {json.dumps(results['prereg'])}")
245
+ print(json.dumps(results["prereg"], indent=2))
246
+ burn_down()
247
+ return results
248
+
249
+
250
+ def smoke():
251
+ x = torch.randn(2, 3, 32, 32)
252
+ assert hp_img(x).shape == x.shape and lp_img(x).shape == x.shape
253
+ w = band_weights(torch.tensor([0.02, 0.5, 0.98]))
254
+ assert w[0].argmax() == 0 and w[2].argmax() == 2
255
+ print("dexp010 smoke PASSED (filters + windows; GPU run is pod work)")
256
+
257
+
258
+ if __name__ == "__main__":
259
+ if "--run" in sys.argv:
260
+ run()
261
+ else:
262
+ smoke()
exp010_controller/results.json ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "config": {
3
+ "steps": 30,
4
+ "guidance": 7.5,
5
+ "seed": 1234,
6
+ "ckpt": "exp008 mb3_s0",
7
+ "sampler": "DDIM step-gated"
8
+ },
9
+ "all_on": {
10
+ "round_trip": {
11
+ "cond": 0.7524,
12
+ "shuffled": 0.5388,
13
+ "gap": 0.2135
14
+ },
15
+ "diversity": 0.19593
16
+ },
17
+ "lesion_band0": {
18
+ "round_trip": {
19
+ "cond": 0.727,
20
+ "shuffled": 0.5291,
21
+ "gap": 0.1979
22
+ },
23
+ "vs_all_on": {
24
+ "lp_change": 0.003607,
25
+ "hp_change": 0.003051,
26
+ "total_change": 0.010842
27
+ },
28
+ "diversity": 0.20773
29
+ },
30
+ "lesion_band1": {
31
+ "round_trip": {
32
+ "cond": 0.72,
33
+ "shuffled": 0.538,
34
+ "gap": 0.1821
35
+ },
36
+ "vs_all_on": {
37
+ "lp_change": 0.018404,
38
+ "hp_change": 0.003947,
39
+ "total_change": 0.033511
40
+ },
41
+ "diversity": 0.21716
42
+ },
43
+ "lesion_band2": {
44
+ "round_trip": {
45
+ "cond": 0.7259,
46
+ "shuffled": 0.5477,
47
+ "gap": 0.1782
48
+ },
49
+ "vs_all_on": {
50
+ "lp_change": 0.072713,
51
+ "hp_change": 0.005081,
52
+ "total_change": 0.094674
53
+ },
54
+ "diversity": 0.29749
55
+ },
56
+ "frozen": {
57
+ "round_trip": {
58
+ "cond": 0.6692,
59
+ "shuffled": 0.5446,
60
+ "gap": 0.1247
61
+ },
62
+ "vs_all_on": {
63
+ "lp_change": 0.080436,
64
+ "hp_change": 0.005172,
65
+ "total_change": 0.103412
66
+ },
67
+ "diversity": 0.33191
68
+ },
69
+ "prereg": {
70
+ "G2_high_band_moves_LP_most": true,
71
+ "G2_low_band_moves_HP_most": false,
72
+ "G3_high_lesion_cuts_diversity": false,
73
+ "note": "image-space coarse-to-fine test; 1-seed battery"
74
+ }
75
+ }