AbstractPhil commited on
Commit
c306994
·
verified ·
1 Parent(s): 5c049df

exp001 shipped (relay certifies: beats frozen + matched LoRA, bit-exact post-train toggle; candidate s0) + README refresh (epred cores primary, nl77 congruency)

Browse files
README.md CHANGED
@@ -19,9 +19,14 @@ geolip program.
19
 
20
  | variant | trunk | trainer path |
21
  |---|---|---|
22
- | SD15-Lune rectified flow | `AbstractPhil/sd15-flow-lune-json-prompt` ckpt-2500 (+ base lune, json-vit) | custom beds (this repo, `substrate/`) |
 
 
23
  | Anima / Cosmos-Predict2 2B DiT | `circlestone-labs/Anima` (NC weights — all derived checkpoints NC) | `AbstractEyes/diffusion-pipe` branch `feat/aleph-adapter` |
24
- | SDXL | `AbstractPhil/geolip-sdxl-aleph` phase-1 ckpts | read-only capacity battery first |
 
 
 
25
 
26
  Sampler of record (Lune family): rectified flow, `v = noise − x0`, Euler on the
27
  **SHIFT=2.5-warped** sigma grid `σ = 2.5u/(1+1.5u)`, `VAE_SCALE 0.18215`. Text
@@ -64,11 +69,13 @@ resolution) so gaps live in a narrow band — the paired design is load-bearing.
64
  | exp | question | status |
65
  |---|---|---|
66
  | exp000_baselines | zero-shot baseline wall (above) | **shipped** |
67
- | exp001_sd15_relay | relay-all16 vs matched LoRA-r32 vs frozen, paired val flow-MSE + round-trip | running |
68
- | exp002_sd15_addrcond | frozen byte-trigram aleph address into the cond stream 4-arm causal | staged |
69
- | exp003_sigma_registers | sign-code separations: what is a diffusion "register"? | staged |
70
- | exp004_anima_relay | relays on the 2B DiT via diffusion-pipe (bf16-matched) | staged |
 
71
  | exp005_sdxl_tree4a | the SDXL capacity battery (guidepost/scaffold/skeleton) | designed |
 
72
 
73
  Code for each experiment ships in its folder with `results.json` from the run
74
  ledger. Substrate modules in `substrate/`.
 
19
 
20
  | variant | trunk | trainer path |
21
  |---|---|---|
22
+ | **SD1.5 core (epred) — primary** | `stable-diffusion-v1-5/stable-diffusion-v1-5`, epsilon objective, natural 77-token prompting | custom beds (this repo, `substrate/`) |
23
+ | **SDXL core (epred) — primary** | `stabilityai/stable-diffusion-xl-base-1.0` | after SD1.5-core certifies; plus the geolip-sdxl-aleph read-only capacity battery |
24
+ | SD15-Lune rectified flow (undertrained exemplar; cheap flow testbed) | `AbstractPhil/sd15-flow-lune-json-prompt` ckpt-2500 (+ base lune, json-vit) | custom beds (this repo, `substrate/`) |
25
  | Anima / Cosmos-Predict2 2B DiT | `circlestone-labs/Anima` (NC weights — all derived checkpoints NC) | `AbstractEyes/diffusion-pipe` branch `feat/aleph-adapter` |
26
+
27
+ **Prompting congruency:** judged work carries BOTH the json-225 chunked
28
+ encoding and standard 77-token plain-English prompting (congruency to the
29
+ natural paradigm).
30
 
31
  Sampler of record (Lune family): rectified flow, `v = noise − x0`, Euler on the
32
  **SHIFT=2.5-warped** sigma grid `σ = 2.5u/(1+1.5u)`, `VAE_SCALE 0.18215`. Text
 
69
  | exp | question | status |
70
  |---|---|---|
71
  | exp000_baselines | zero-shot baseline wall (above) | **shipped** |
72
+ | exp000b_natural | natural-paradigm extension: nl77 arms + core epred SD15/SDXL stock-pipeline baselines | running |
73
+ | exp001_sd15_relay | relay-all16 vs matched LoRA-r32 vs frozen: **relay beats both; LoRA lands below frozen; post-train toggle bit-exact** | **shipped (candidate, s0)** |
74
+ | exp002_sd15_addrcond | frozen byte-trigram aleph address into the cond stream — 4-arm causal | running |
75
+ | exp003_sigma_registers | sign-code separations: what is a diffusion "register"? (+prompt77 register) | running |
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 | relay vs LoRA on the CORE EPRED SD1.5 (epsilon objective, natural cond) | running |
79
 
80
  Code for each experiment ships in its folder with `results.json` from the run
81
  ledger. Substrate modules in `substrate/`.
exp001_sd15_relay/README.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # exp001_sd15_relay — relay machinery certification on SD15-Lune (CANDIDATE, s0)
2
+
3
+ **Question.** Does the certified text-line relay recipe (per-block RelayPatch2D:
4
+ multi-slot closed-form aleph read → SquaredReLU patchwork, zero-init out
5
+ weight+bias, gate init −3.0, bit-exact toggle) carry to a diffusion trunk, and
6
+ does it beat a parameter-matched LoRA under the identical objective?
7
+
8
+ **Design.** Frozen `sd15-flow-lune-json-prompt` ckpt-2500 UNet (fp32 — adapter
9
+ dtype matches trunk dtype per the line's dtype law). Three arms on one shared
10
+ cache (4096 train / 256 val rows of `synthetic-object-relations-json`, latents
11
+ + 225-token json conditioning, identical across arms):
12
+
13
+ | arm | trainable | notes |
14
+ |---|---|---|
15
+ | frozen | 0 | reference, re-measured in-run |
16
+ | relay_all16 | 3,227,568 | all 16 BasicTransformerBlocks |
17
+ | lora_r32 | 3,182,592 | cross-attn q/k/v/out, rank 32 (param ratio 1.014) |
18
+
19
+ Objective = the json trainer verbatim (σ~U(0,1) → SHIFT-2.5 warp,
20
+ x_t = noise·σ′ + latents·(1−σ′), v-target MSE, 10% CFG dropout). Both trained
21
+ arms: 3000 steps, batch 16, **pure Adam wd=0**, gradient checkpointing.
22
+ Val = paired flow-MSE on FIXED per-row (noise, σ), fp32, with per-σ-band
23
+ breakdown. Round-trip judge = exp000's exact 24 rows and machinery.
24
+
25
+ **Results** (`results.json`):
26
+
27
+ | arm | val flow-MSE | Δ vs frozen | round-trip gap (exp000 base: +0.2099) |
28
+ |---|---|---|---|
29
+ | frozen | 0.52241 | — | — |
30
+ | **relay_all16** | **0.51796** | **−0.85%** | **+0.2052** (preserved) |
31
+ | lora_r32 | 0.52503 | **+0.50% (worse)** | +0.1694 (degraded) |
32
+
33
+ - **Preregistration HIT:** relay ≥ matched LoRA on paired val flow-MSE — and
34
+ the LoRA arm landed *below frozen* while degrading conditional grounding by
35
+ ~0.04; the relay improved val-MSE while preserving grounding.
36
+ - **Toggle law held post-train, bit-exact:** relays-disabled val reproduces the
37
+ frozen row to 16 decimals (in-bed assert).
38
+ - **Gate telemetry:** mean 0.0432 (init 0.0474 → mild shrink, the v35
39
+ gate-shrink direction), range 0.031–0.060 — sits just **above** the LM-line
40
+ 0.012–0.03 gate band. Prereg P3 near-miss → the band's scope does not simply
41
+ extend to diffusion relays at 3k steps; scope finding, not a failure.
42
+ - σ-band breakdown: relay improves all four bands; largest gain at high σ
43
+ (band0 0.55996 → 0.55319).
44
+
45
+ **Honest caveats.** Single seed (CANDIDATE); 3k-step short-train — this is a
46
+ *machinery certification*, not a capability claim; deltas are ~1% of val MSE;
47
+ the LoRA control uses one standard placement (cross-attn q/k/v/out) at one
48
+ rank; round-trip n=24. Cost: relay 1.87 s/step, LoRA 1.68 s/step, ~11GB peak
49
+ each; whole experiment ≈ 3.1 GPU-h on an RTX 6000 Ada (incl. an OOM'd first
50
+ attempt at batch 32 without checkpointing — the frozen trunk still retains its
51
+ full activation graph for adapter gradients; batch 16 + checkpointing is the
52
+ recorded recipe).
53
+
54
+ **Checkpoints.** `relay_all16_s0.pt` (dims rebuild from the state dict;
55
+ `aleph_diffusion_core.load_relay_stack`), `lora_r32_s0/` (PEFT).
exp001_sd15_relay/dexp001_sd15_relay.py ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """dexp001_sd15_relay.py — exp001: SD15-Lune relay machinery certification.
2
+
3
+ Arms (all fp32 trunk, identical cached data, identical paired val):
4
+ frozen — re-measured reference (never inherited).
5
+ relay_all16— RelayPatch2D on all 16 BasicTransformerBlocks (adapters-only
6
+ train; pure Adam wd=0; zero-init W+b; gate -3.0).
7
+ lora_r32 — matched-param control: PEFT LoRA on cross-attn (attn2
8
+ q/k/v/out), rank 32 (param count printed + compared).
9
+
10
+ Objective = the trainer of record VERBATIM (sd15_flow_lune_json_trainer.py:
11
+ 310-335): s~U(0,1) -> s'=2.5s/(1+1.5s), t=s'*1000, x_t = noise*s' +
12
+ latents*(1-s'), v = noise - latents, per-sample MSE, CFG dropout 0.1
13
+ (embeddings zeroed). latents = vae_sample * 0.18215 (cached once, all arms
14
+ identical).
15
+
16
+ Judged (fp32, paired):
17
+ 1) val flow-MSE on 256 held-out rows with FIXED per-row (noise, sigma).
18
+ 2) round-trip CLIP-L cond-vs-SHUFFLED gap on the SAME 24 tail rows as
19
+ exp000 (baseline wall: json_ckpt2500 +0.2099).
20
+ 3) P-TOGGLE post-train: relays disabled == frozen val-MSE bit-exact.
21
+ 4) gate telemetry per sigma band (0.012-0.03 band prereg — first non-LM test).
22
+
23
+ Preregistration (charter 2026-07-16): relay >= lora on paired val-MSE at
24
+ matched params; parity gates green incl. post-train; gate means vs the band.
25
+ Honest negative: lora wins -> Tier B demoted to candidate, Tier A leads.
26
+
27
+ Pod: python3 pod2/dexp001_sd15_relay.py --run [--steps 3000]
28
+ """
29
+ from __future__ import annotations
30
+
31
+ import io
32
+ import json
33
+ import os
34
+ import sys
35
+ import time
36
+
37
+ sys.path[:0] = ["pod2", "."]
38
+
39
+ import torch
40
+ import torch.nn.functional as F
41
+
42
+ from pod_ledger import ledger_run, note, burn_down
43
+ from aleph_diffusion_core import (derangement, gate_stats, save_relay_stack,
44
+ sigma_band, SIGMA_BANDS)
45
+ from d1_lune_sampler import encode_clip_225, flow_sample, decode
46
+ from d1_substrate import attach_relays, enumerate_sd15_sites, MEM_FRACTION
47
+
48
+ DATASET = "AbstractPhil/synthetic-object-relations-json"
49
+ SD_BASE = "stable-diffusion-v1-5/stable-diffusion-v1-5"
50
+ SD_REPO = "AbstractPhil/sd15-flow-lune-json-prompt"
51
+ SD_SUB = "checkpoint-00002500/unet"
52
+ VAE_SCALE, SHIFT = 0.18215, 2.5
53
+ N_TRAIN, N_VAL, N_JUDGE = 4096, 256, 24
54
+ # batch 32 no-checkpointing OOM'd the 43.6GB cap (2026-07-16 19:35Z — the
55
+ # frozen trunk still retains its FULL activation graph for relay grads);
56
+ # checkpointing default-on rider now honored in load_unet()
57
+ BATCH, LR, CFG_DROPOUT = int(os.environ.get("DEXP1_BATCH", "16")), 1e-3, 0.1
58
+ STEPS = int(os.environ.get("DEXP1_STEPS", "3000"))
59
+ SEED = 0
60
+ DATA_DIR = ("/workspace/data/dexp001" if os.path.isdir("/workspace")
61
+ else os.path.join(os.environ.get("GEOLIP_DATA", "./data"),
62
+ "dexp001"))
63
+ CKPT_DIR = ("/workspace/ckpts2/dexp001" if os.path.isdir("/workspace")
64
+ else DATA_DIR)
65
+
66
+
67
+ # ── stage 0: cache (latents + text embeds, once; all arms share) ────────────
68
+
69
+ def _iter_rows(need: int):
70
+ from huggingface_hub import HfApi, hf_hub_download
71
+ import pyarrow.parquet as pq
72
+ api = HfApi()
73
+ files = sorted(f for f in api.list_repo_files(DATASET, repo_type="dataset")
74
+ if f.endswith(".parquet"))
75
+ got = 0
76
+ for fname in files:
77
+ path = hf_hub_download(DATASET, fname, repo_type="dataset")
78
+ tbl = pq.read_table(path, columns=None)
79
+ for r in tbl.to_pylist():
80
+ yield fname, r
81
+ got += 1
82
+ if got >= need:
83
+ return
84
+
85
+
86
+ def build_cache(device="cuda"):
87
+ cache_f = os.path.join(DATA_DIR, "cache.pt")
88
+ if os.path.exists(cache_f):
89
+ print(f"[cache] exists: {cache_f} (DATA_ROOT pinned — never move)")
90
+ return cache_f
91
+ os.makedirs(DATA_DIR, exist_ok=True)
92
+ from PIL import Image
93
+ import numpy as np
94
+ from diffusers import AutoencoderKL
95
+ from transformers import CLIPTextModel, CLIPTokenizer
96
+ vae = AutoencoderKL.from_pretrained(
97
+ SD_BASE, subfolder="vae", torch_dtype=torch.float32).to(device).eval()
98
+ tok = CLIPTokenizer.from_pretrained(SD_BASE, subfolder="tokenizer")
99
+ te = CLIPTextModel.from_pretrained(
100
+ SD_BASE, subfolder="text_encoder",
101
+ torch_dtype=torch.float32).to(device).eval()
102
+ g = torch.Generator(device=device).manual_seed(SEED)
103
+
104
+ lat, ehs = [], []
105
+ buf_img, buf_txt = [], []
106
+
107
+ @torch.no_grad()
108
+ def flush():
109
+ if not buf_img:
110
+ return
111
+ px = torch.stack(buf_img).to(device)
112
+ lat.append((vae.encode(px).latent_dist.sample(generator=g)
113
+ * VAE_SCALE).cpu())
114
+ ehs.append(encode_clip_225(buf_txt, tok, te, device).cpu())
115
+ buf_img.clear()
116
+ buf_txt.clear()
117
+
118
+ n = 0
119
+ for fname, r in _iter_rows(N_TRAIN + N_VAL):
120
+ img = r["image"]
121
+ img = img.get("bytes") if isinstance(img, dict) else img
122
+ im = Image.open(io.BytesIO(img)).convert("RGB").resize((512, 512))
123
+ arr = torch.from_numpy(np.asarray(im)).float() / 127.5 - 1.0
124
+ buf_img.append(arr.permute(2, 0, 1))
125
+ jp = r["json_prompt"]
126
+ buf_txt.append(jp if isinstance(jp, str) else json.dumps(jp))
127
+ n += 1
128
+ if len(buf_img) == 16:
129
+ flush()
130
+ if n % 512 == 0:
131
+ print(f"[cache] {n}/{N_TRAIN + N_VAL}", flush=True)
132
+ flush()
133
+ lat, ehs = torch.cat(lat), torch.cat(ehs)
134
+ gv = torch.Generator().manual_seed(SEED + 1)
135
+ val_noise = torch.randn(N_VAL, 4, 64, 64, generator=gv)
136
+ u = torch.linspace(0.02, 0.98, N_VAL)
137
+ val_sigma = (SHIFT * u) / (1 + (SHIFT - 1) * u)
138
+ torch.save({"lat": lat[:N_TRAIN], "ehs": ehs[:N_TRAIN],
139
+ "val_lat": lat[N_TRAIN:], "val_ehs": ehs[N_TRAIN:],
140
+ "val_noise": val_noise, "val_sigma": val_sigma,
141
+ "data_root": DATA_DIR}, cache_f)
142
+ print(f"[cache] built {cache_f}: train {N_TRAIN}, val {N_VAL}", flush=True)
143
+ del vae, te
144
+ torch.cuda.empty_cache()
145
+ return cache_f
146
+
147
+
148
+ # ── the objective (trainer-verbatim) ─────────────────────────────────────────
149
+
150
+ def flow_loss(unet, lat, ehs, gen, device):
151
+ bsz = lat.shape[0]
152
+ drop = torch.rand(bsz, generator=gen, device=device) < CFG_DROPOUT
153
+ ehs = ehs.clone()
154
+ ehs[drop] = 0
155
+ s = torch.rand(bsz, generator=gen, device=device)
156
+ s = (SHIFT * s) / (1 + (SHIFT - 1) * s)
157
+ t = s * 1000
158
+ s4 = s[:, None, None, None]
159
+ noise = torch.randn(lat.shape, generator=gen, device=device)
160
+ noisy = noise * s4 + lat * (1 - s4)
161
+ target = noise - lat
162
+ pred = unet(noisy, t, ehs, return_dict=False)[0]
163
+ return F.mse_loss(pred, target)
164
+
165
+
166
+ @torch.no_grad()
167
+ def val_mse(unet, cache, device):
168
+ """Paired: FIXED per-row (noise, sigma); fp32; per-band breakdown."""
169
+ tot, per_band = [], {i: [] for i in range(len(SIGMA_BANDS))}
170
+ for i in range(0, N_VAL, 32):
171
+ lat = cache["val_lat"][i:i + 32].to(device)
172
+ ehs = cache["val_ehs"][i:i + 32].to(device)
173
+ noise = cache["val_noise"][i:i + 32].to(device)
174
+ s = cache["val_sigma"][i:i + 32].to(device)
175
+ s4 = s[:, None, None, None]
176
+ pred = unet(noise * s4 + lat * (1 - s4), s * 1000, ehs,
177
+ return_dict=False)[0]
178
+ mse = ((pred - (noise - lat)) ** 2).mean(dim=(1, 2, 3))
179
+ tot += mse.tolist()
180
+ for j, sv in enumerate(s.tolist()):
181
+ per_band[sigma_band(sv)].append(mse[j].item())
182
+ return {"mean": sum(tot) / len(tot),
183
+ "per_band": {f"band{k}": round(sum(v) / max(len(v), 1), 5)
184
+ for k, v in per_band.items()}}
185
+
186
+
187
+ # ── round-trip judge (exp000-identical rows + machinery) ────────────────────
188
+
189
+ @torch.no_grad()
190
+ def round_trip(unet, device):
191
+ from d1_exp000_baselines import load_rows, judge_selftest
192
+ from PIL import Image
193
+ import numpy as np
194
+ from transformers import (CLIPTextModel, CLIPTokenizer, CLIPModel,
195
+ CLIPProcessor)
196
+ from diffusers import AutoencoderKL
197
+ rows = load_rows(N_JUDGE)
198
+ tok = CLIPTokenizer.from_pretrained(SD_BASE, subfolder="tokenizer")
199
+ te = CLIPTextModel.from_pretrained(
200
+ SD_BASE, subfolder="text_encoder",
201
+ torch_dtype=torch.float32).to(device).eval()
202
+ vae = AutoencoderKL.from_pretrained(
203
+ SD_BASE, subfolder="vae", torch_dtype=torch.float32).to(device).eval()
204
+ clip = CLIPModel.from_pretrained(
205
+ "openai/clip-vit-large-patch14",
206
+ torch_dtype=torch.float32).to(device).eval()
207
+ cproc = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")
208
+ feat = judge_selftest(clip, cproc, device)
209
+ prompts = [r["json_prompt"] for r in rows]
210
+ perm = derangement(len(prompts), seed=1234)
211
+ orig = torch.cat([
212
+ feat(Image.open(io.BytesIO(r["image_bytes"])).convert("RGB"))
213
+ for r in rows])
214
+ out = {}
215
+ for arm, ps in (("cond", prompts),
216
+ ("shuffled", [prompts[i] for i in perm.tolist()])):
217
+ ehs = encode_clip_225(ps, tok, te, device)
218
+ cos = []
219
+ for i in range(0, len(ps), 6):
220
+ latg = flow_sample(unet, ehs[i:i + 6], n_steps=30, guidance=6.0,
221
+ seed=1234 + i, device=device)
222
+ imgs = decode(vae, latg)
223
+ pil = [Image.fromarray((im * 255).astype(np.uint8))
224
+ for im in imgs]
225
+ f = torch.cat([feat(p) for p in pil])
226
+ cos += (f * orig[i:i + 6]).sum(-1).tolist()
227
+ out[arm] = round(sum(cos) / len(cos), 4)
228
+ out["cond_minus_shuffled"] = round(out["cond"] - out["shuffled"], 4)
229
+ del te, vae, clip
230
+ torch.cuda.empty_cache()
231
+ return out
232
+
233
+
234
+ # ── arms ─────────────────────────���───────────────────────────────────────────
235
+
236
+ def load_unet(device):
237
+ from diffusers import UNet2DConditionModel
238
+ unet = UNet2DConditionModel.from_pretrained(
239
+ SD_REPO, subfolder=SD_SUB, torch_dtype=torch.float32).to(device)
240
+ unet.requires_grad_(False)
241
+ unet.eval()
242
+ unet.enable_gradient_checkpointing() # rider: default-on (OOM-earned)
243
+ return unet
244
+
245
+
246
+ def train_loop(unet, params, cache, device, label):
247
+ opt = torch.optim.Adam(params, lr=LR, weight_decay=0.0) # pure Adam law
248
+ gen = torch.Generator(device=device).manual_seed(SEED + 42)
249
+ idx_gen = torch.Generator().manual_seed(SEED + 7)
250
+ torch.cuda.reset_peak_memory_stats()
251
+ t0, losses = time.time(), []
252
+ for step in range(1, STEPS + 1):
253
+ sel = torch.randint(0, N_TRAIN, (BATCH,), generator=idx_gen)
254
+ lat = cache["lat"][sel].to(device)
255
+ ehs = cache["ehs"][sel].to(device)
256
+ loss = flow_loss(unet, lat, ehs, gen, device)
257
+ loss.backward()
258
+ opt.step()
259
+ opt.zero_grad(set_to_none=True)
260
+ losses.append(loss.item())
261
+ if step == 50 or step % 500 == 0:
262
+ print(f"[{label}] step {step}: loss {loss.item():.4f} | "
263
+ f"{(time.time() - t0) / step:.2f}s/step | "
264
+ f"peak {torch.cuda.max_memory_allocated() / 2**30:.1f}GB",
265
+ flush=True)
266
+ return {"steps": STEPS, "final_loss_ma50":
267
+ round(sum(losses[-50:]) / 50, 5),
268
+ "s_per_step": round((time.time() - t0) / STEPS, 3),
269
+ "peak_mem_gb":
270
+ round(torch.cuda.max_memory_allocated() / 2**30, 2)}
271
+
272
+
273
+ def arm_frozen(cache, device):
274
+ unet = load_unet(device)
275
+ r = {"val": val_mse(unet, cache, device)}
276
+ del unet
277
+ torch.cuda.empty_cache()
278
+ return r
279
+
280
+
281
+ def arm_relay(cache, device):
282
+ unet = load_unet(device)
283
+ relays, names = attach_relays(unet)
284
+ n_params = sum(p.numel() for p in relays.parameters())
285
+ print(f"[relay] {len(relays)} sites, {n_params:,} trainable", flush=True)
286
+ for rl in relays:
287
+ rl.train()
288
+ stats = train_loop(unet, relays.parameters(), cache, device, "relay")
289
+ for rl in relays:
290
+ rl.eval()
291
+ v_on = val_mse(unet, cache, device)
292
+ for rl in relays: # P-TOGGLE post-train
293
+ rl.enabled = False
294
+ v_off = val_mse(unet, cache, device)
295
+ for rl in relays:
296
+ rl.enabled = True
297
+ os.makedirs(CKPT_DIR, exist_ok=True)
298
+ save_relay_stack(relays, os.path.join(CKPT_DIR, "relay_all16_s0.pt"))
299
+ rt = round_trip(unet, device)
300
+ res = {"n_params": n_params, "train": stats, "val": v_on,
301
+ "val_toggled_off": v_off, "gates": gate_stats(relays),
302
+ "round_trip": rt}
303
+ del unet, relays
304
+ torch.cuda.empty_cache()
305
+ return res
306
+
307
+
308
+ def arm_lora(cache, device):
309
+ from peft import LoraConfig, get_peft_model
310
+ unet = load_unet(device)
311
+ targets = [n for n, m in unet.named_modules()
312
+ if isinstance(m, torch.nn.Linear) and "attn2" in n
313
+ and n.split(".")[-1] in ("to_q", "to_k", "to_v")
314
+ or (isinstance(m, torch.nn.Linear) and "attn2" in n
315
+ and n.endswith("to_out.0"))]
316
+ cfg = LoraConfig(r=32, lora_alpha=32, target_modules=targets,
317
+ lora_dropout=0.0)
318
+ unet = get_peft_model(unet, cfg)
319
+ params = [p for p in unet.parameters() if p.requires_grad]
320
+ n_params = sum(p.numel() for p in params)
321
+ print(f"[lora] r=32 on {len(targets)} linears, {n_params:,} trainable",
322
+ flush=True)
323
+ unet.train()
324
+ stats = train_loop(unet, params, cache, device, "lora")
325
+ unet.eval()
326
+ v = val_mse(unet, cache, device)
327
+ unet.save_pretrained(os.path.join(CKPT_DIR, "lora_r32_s0"))
328
+ rt = round_trip(unet, device)
329
+ res = {"n_params": n_params, "train": stats, "val": v, "round_trip": rt}
330
+ del unet
331
+ torch.cuda.empty_cache()
332
+ return res
333
+
334
+
335
+ def run(device="cuda"):
336
+ torch.cuda.set_per_process_memory_fraction(MEM_FRACTION, 0)
337
+ results = {"config": {"steps": STEPS, "batch": BATCH, "lr": LR,
338
+ "n_train": N_TRAIN, "n_val": N_VAL, "seed": SEED,
339
+ "optimizer": "torch.optim.Adam wd=0"}}
340
+ with ledger_run("dexp001 cache build", budget_h=0.5):
341
+ build_cache(device)
342
+ cache = torch.load(os.path.join(DATA_DIR, "cache.pt"),
343
+ map_location="cpu", weights_only=True)
344
+ with ledger_run("dexp001 frozen reference", budget_h=0.2) as h:
345
+ results["frozen"] = arm_frozen(cache, device)
346
+ h["verdict"] = f"val {results['frozen']['val']['mean']:.5f}"
347
+ with ledger_run("dexp001 relay_all16 s0", budget_h=2.0) as h:
348
+ results["relay_all16"] = arm_relay(cache, device)
349
+ # P-TOGGLE assert: toggled-off == frozen (bit-exact val path)
350
+ d = abs(results["relay_all16"]["val_toggled_off"]["mean"]
351
+ - results["frozen"]["val"]["mean"])
352
+ assert d < 1e-9, f"post-train toggle parity broken: {d}"
353
+ h["verdict"] = (f"val {results['relay_all16']['val']['mean']:.5f} "
354
+ f"rt {results['relay_all16']['round_trip']['cond_minus_shuffled']:+.4f}")
355
+ with ledger_run("dexp001 lora_r32 s0", budget_h=2.0) as h:
356
+ results["lora_r32"] = arm_lora(cache, device)
357
+ h["verdict"] = (f"val {results['lora_r32']['val']['mean']:.5f} "
358
+ f"rt {results['lora_r32']['round_trip']['cond_minus_shuffled']:+.4f}")
359
+
360
+ rv = results["relay_all16"]["val"]["mean"]
361
+ lv = results["lora_r32"]["val"]["mean"]
362
+ fv = results["frozen"]["val"]["mean"]
363
+ results["verdict"] = {
364
+ "relay_beats_frozen": rv < fv,
365
+ "relay_vs_lora": "relay" if rv <= lv else "lora",
366
+ "param_ratio": round(results["relay_all16"]["n_params"]
367
+ / results["lora_r32"]["n_params"], 3),
368
+ "note": "prereg: relay >= lora at matched params; 1-seed CANDIDATE",
369
+ }
370
+ os.makedirs(DATA_DIR, exist_ok=True)
371
+ with open(os.path.join(DATA_DIR, "results.json"), "w") as f:
372
+ json.dump(results, f, indent=2)
373
+ note(f"dexp001 verdict: {json.dumps(results['verdict'])}")
374
+ print(json.dumps(results["verdict"], indent=2))
375
+ burn_down()
376
+ return results
377
+
378
+
379
+ def smoke():
380
+ assert STEPS > 0 and N_TRAIN > N_VAL
381
+ p = derangement(N_JUDGE, seed=1234)
382
+ assert not (p == torch.arange(N_JUDGE)).any()
383
+ print("dexp001 smoke PASSED (parse; GPU run is pod work)")
384
+
385
+
386
+ if __name__ == "__main__":
387
+ if "--run" in sys.argv:
388
+ run()
389
+ else:
390
+ smoke()
exp001_sd15_relay/lora_r32_s0/README.md ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ base_model: AbstractPhil/sd15-flow-lune-json-prompt
3
+ library_name: peft
4
+ tags:
5
+ - lora
6
+ ---
7
+
8
+ # Model Card for Model ID
9
+
10
+ <!-- Provide a quick summary of what the model is/does. -->
11
+
12
+
13
+
14
+ ## Model Details
15
+
16
+ ### Model Description
17
+
18
+ <!-- Provide a longer summary of what this model is. -->
19
+
20
+
21
+
22
+ - **Developed by:** [More Information Needed]
23
+ - **Funded by [optional]:** [More Information Needed]
24
+ - **Shared by [optional]:** [More Information Needed]
25
+ - **Model type:** [More Information Needed]
26
+ - **Language(s) (NLP):** [More Information Needed]
27
+ - **License:** [More Information Needed]
28
+ - **Finetuned from model [optional]:** [More Information Needed]
29
+
30
+ ### Model Sources [optional]
31
+
32
+ <!-- Provide the basic links for the model. -->
33
+
34
+ - **Repository:** [More Information Needed]
35
+ - **Paper [optional]:** [More Information Needed]
36
+ - **Demo [optional]:** [More Information Needed]
37
+
38
+ ## Uses
39
+
40
+ <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
41
+
42
+ ### Direct Use
43
+
44
+ <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
45
+
46
+ [More Information Needed]
47
+
48
+ ### Downstream Use [optional]
49
+
50
+ <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
51
+
52
+ [More Information Needed]
53
+
54
+ ### Out-of-Scope Use
55
+
56
+ <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
57
+
58
+ [More Information Needed]
59
+
60
+ ## Bias, Risks, and Limitations
61
+
62
+ <!-- This section is meant to convey both technical and sociotechnical limitations. -->
63
+
64
+ [More Information Needed]
65
+
66
+ ### Recommendations
67
+
68
+ <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
69
+
70
+ Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
71
+
72
+ ## How to Get Started with the Model
73
+
74
+ Use the code below to get started with the model.
75
+
76
+ [More Information Needed]
77
+
78
+ ## Training Details
79
+
80
+ ### Training Data
81
+
82
+ <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
83
+
84
+ [More Information Needed]
85
+
86
+ ### Training Procedure
87
+
88
+ <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
89
+
90
+ #### Preprocessing [optional]
91
+
92
+ [More Information Needed]
93
+
94
+
95
+ #### Training Hyperparameters
96
+
97
+ - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
98
+
99
+ #### Speeds, Sizes, Times [optional]
100
+
101
+ <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
102
+
103
+ [More Information Needed]
104
+
105
+ ## Evaluation
106
+
107
+ <!-- This section describes the evaluation protocols and provides the results. -->
108
+
109
+ ### Testing Data, Factors & Metrics
110
+
111
+ #### Testing Data
112
+
113
+ <!-- This should link to a Dataset Card if possible. -->
114
+
115
+ [More Information Needed]
116
+
117
+ #### Factors
118
+
119
+ <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
120
+
121
+ [More Information Needed]
122
+
123
+ #### Metrics
124
+
125
+ <!-- These are the evaluation metrics being used, ideally with a description of why. -->
126
+
127
+ [More Information Needed]
128
+
129
+ ### Results
130
+
131
+ [More Information Needed]
132
+
133
+ #### Summary
134
+
135
+
136
+
137
+ ## Model Examination [optional]
138
+
139
+ <!-- Relevant interpretability work for the model goes here -->
140
+
141
+ [More Information Needed]
142
+
143
+ ## Environmental Impact
144
+
145
+ <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
146
+
147
+ Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
148
+
149
+ - **Hardware Type:** [More Information Needed]
150
+ - **Hours used:** [More Information Needed]
151
+ - **Cloud Provider:** [More Information Needed]
152
+ - **Compute Region:** [More Information Needed]
153
+ - **Carbon Emitted:** [More Information Needed]
154
+
155
+ ## Technical Specifications [optional]
156
+
157
+ ### Model Architecture and Objective
158
+
159
+ [More Information Needed]
160
+
161
+ ### Compute Infrastructure
162
+
163
+ [More Information Needed]
164
+
165
+ #### Hardware
166
+
167
+ [More Information Needed]
168
+
169
+ #### Software
170
+
171
+ [More Information Needed]
172
+
173
+ ## Citation [optional]
174
+
175
+ <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
176
+
177
+ **BibTeX:**
178
+
179
+ [More Information Needed]
180
+
181
+ **APA:**
182
+
183
+ [More Information Needed]
184
+
185
+ ## Glossary [optional]
186
+
187
+ <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
188
+
189
+ [More Information Needed]
190
+
191
+ ## More Information [optional]
192
+
193
+ [More Information Needed]
194
+
195
+ ## Model Card Authors [optional]
196
+
197
+ [More Information Needed]
198
+
199
+ ## Model Card Contact
200
+
201
+ [More Information Needed]
202
+ ### Framework versions
203
+
204
+ - PEFT 0.19.1
exp001_sd15_relay/lora_r32_s0/adapter_config.json ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alora_invocation_tokens": null,
3
+ "alpha_pattern": {},
4
+ "arrow_config": null,
5
+ "auto_mapping": {
6
+ "base_model_class": "UNet2DConditionModel",
7
+ "parent_library": "diffusers.models.unets.unet_2d_condition"
8
+ },
9
+ "base_model_name_or_path": null,
10
+ "bias": "none",
11
+ "corda_config": null,
12
+ "ensure_weight_tying": false,
13
+ "eva_config": null,
14
+ "exclude_modules": null,
15
+ "fan_in_fan_out": false,
16
+ "inference_mode": true,
17
+ "init_lora_weights": true,
18
+ "layer_replication": null,
19
+ "layers_pattern": null,
20
+ "layers_to_transform": null,
21
+ "loftq_config": {},
22
+ "lora_alpha": 32,
23
+ "lora_bias": false,
24
+ "lora_dropout": 0.0,
25
+ "lora_ga_config": null,
26
+ "megatron_config": null,
27
+ "megatron_core": "megatron.core",
28
+ "modules_to_save": null,
29
+ "peft_type": "LORA",
30
+ "peft_version": "0.19.1",
31
+ "qalora_group_size": 16,
32
+ "r": 32,
33
+ "rank_pattern": {},
34
+ "revision": null,
35
+ "target_modules": [
36
+ "attn2.to_q",
37
+ "attn2.to_out.0",
38
+ "attn2.to_v",
39
+ "attn2.to_k"
40
+ ],
41
+ "target_parameters": null,
42
+ "task_type": null,
43
+ "trainable_token_indices": null,
44
+ "use_bdlora": null,
45
+ "use_dora": false,
46
+ "use_qalora": false,
47
+ "use_rslora": false
48
+ }
exp001_sd15_relay/lora_r32_s0/adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2cfed64ef4fbaeb6c2a2b506b15b36226f4504f2c047f66b49acb23cf043f85c
3
+ size 12750664
exp001_sd15_relay/relay_all16_s0.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d1ff74a91bdc91c553b8a4d99906c54e5997dbe283bf1fe6bc0000992956acd2
3
+ size 12979593
exp001_sd15_relay/results.json ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "config": {
3
+ "steps": 3000,
4
+ "batch": 16,
5
+ "lr": 0.001,
6
+ "n_train": 4096,
7
+ "n_val": 256,
8
+ "seed": 0,
9
+ "optimizer": "torch.optim.Adam wd=0"
10
+ },
11
+ "frozen": {
12
+ "val": {
13
+ "mean": 0.5224103183136322,
14
+ "per_band": {
15
+ "band0": 0.55996,
16
+ "band1": 0.49406,
17
+ "band2": 0.43805,
18
+ "band3": 0.57615
19
+ }
20
+ }
21
+ },
22
+ "relay_all16": {
23
+ "n_params": 3227568,
24
+ "train": {
25
+ "steps": 3000,
26
+ "final_loss_ma50": 0.51463,
27
+ "s_per_step": 1.866,
28
+ "peak_mem_gb": 11.19
29
+ },
30
+ "val": {
31
+ "mean": 0.5179595574736595,
32
+ "per_band": {
33
+ "band0": 0.55319,
34
+ "band1": 0.49076,
35
+ "band2": 0.43648,
36
+ "band3": 0.57401
37
+ }
38
+ },
39
+ "val_toggled_off": {
40
+ "mean": 0.5224103183136322,
41
+ "per_band": {
42
+ "band0": 0.55996,
43
+ "band1": 0.49406,
44
+ "band2": 0.43805,
45
+ "band3": 0.57615
46
+ }
47
+ },
48
+ "gates": {
49
+ "gate_mean": 0.0432,
50
+ "gate_min": 0.03114,
51
+ "gate_max": 0.06005
52
+ },
53
+ "round_trip": {
54
+ "cond": 0.7614,
55
+ "shuffled": 0.5562,
56
+ "cond_minus_shuffled": 0.2052
57
+ }
58
+ },
59
+ "lora_r32": {
60
+ "n_params": 3182592,
61
+ "train": {
62
+ "steps": 3000,
63
+ "final_loss_ma50": 0.51787,
64
+ "s_per_step": 1.682,
65
+ "peak_mem_gb": 10.1
66
+ },
67
+ "val": {
68
+ "mean": 0.5250325485831127,
69
+ "per_band": {
70
+ "band0": 0.56475,
71
+ "band1": 0.49516,
72
+ "band2": 0.43908,
73
+ "band3": 0.57589
74
+ }
75
+ },
76
+ "round_trip": {
77
+ "cond": 0.7208,
78
+ "shuffled": 0.5514,
79
+ "cond_minus_shuffled": 0.1694
80
+ }
81
+ },
82
+ "verdict": {
83
+ "relay_beats_frozen": true,
84
+ "relay_vs_lora": "relay",
85
+ "param_ratio": 1.014,
86
+ "note": "prereg: relay >= lora at matched params; 1-seed CANDIDATE"
87
+ }
88
+ }