AbstractPhil commited on
Commit
ac13ae9
·
verified ·
1 Parent(s): a41d30b

exp006 shipped: relay certifies on the CORE EPRED SD1.5 (beats frozen + matched LoRA; grounding gained; substrate-dependent gate growth)

Browse files
README.md CHANGED
@@ -75,7 +75,7 @@ resolution) so gaps live in a narrow band — the paired design is load-bearing.
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/`.
 
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 | 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
 
80
  Code for each experiment ships in its folder with `results.json` from the run
81
  ledger. Substrate modules in `substrate/`.
exp006_sd15core_relay/README.md ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # exp006_sd15core_relay — relays on the CORE EPRED SD1.5 (CANDIDATE, s0)
2
+
3
+ **Question.** Does the relay recipe certify on the primary substrate — stock
4
+ `stable-diffusion-v1-5`, epsilon objective on the shipped schedule, natural
5
+ 77-token plain-English conditioning — and does it beat matched LoRA there?
6
+
7
+ **Design.** exp001's design transplanted to the natural paradigm: frozen fp32
8
+ stock UNet; three arms on one shared cache (4096/256 rows, latents + nl77
9
+ conditioning); epsilon-prediction loss with the stock scaled-linear schedule,
10
+ t~U{0..999}, 10% CFG dropout; 3000 steps, batch 16, pure Adam wd=0, gradient
11
+ checkpointing; paired val on FIXED per-row (noise, t), fp32. Round-trip judge
12
+ via the standard StableDiffusionPipeline (stock scheduler) on exp000's rows,
13
+ read against exp000b's `sd15_epred_core` baseline row (+0.1809).
14
+
15
+ **Results** (`results.json`):
16
+
17
+ | arm | trainable | val eps-MSE | Δ vs frozen | round-trip gap |
18
+ |---|---|---|---|---|
19
+ | frozen | 0 | 0.124788 | — | (+0.1809 baseline) |
20
+ | **relay_all16** | 3,227,568 | **0.121698** | **−2.5%** | **+0.2172** |
21
+ | lora_r32 | 3,182,592 | 0.122674 | −1.7% | +0.1596 |
22
+
23
+ **Findings (candidate, s0).**
24
+ 1. **Relay ≥ matched LoRA, 2-for-2 across substrates** (here and exp001 on
25
+ the Lune flow trunk). On the core, LoRA does help val (unlike Lune where
26
+ it landed below frozen) — but stays behind the relay.
27
+ 2. **Grounding: relay gains, LoRA trades away.** The relay arm *improved*
28
+ natural-prompt round-trip grounding over the zero-shot core baseline
29
+ (+0.1809 → +0.2172) while LoRA degraded it (+0.1596). Same direction as
30
+ exp001; stronger effect.
31
+ 3. **Gate dynamics are substrate-dependent:** core-epred relay gates GREW
32
+ (0.0474 init → mean 0.0700, max 0.0986 — the "trunk opts in" mechanism
33
+ from the text line), where Lune relay gates shrank (exp001, mean 0.0432).
34
+ Neither sits in the LM-line 0.012–0.03 band.
35
+ 4. **Toggle law held post-train, bit-exact** (toggled-off val ≡ frozen).
36
+
37
+ **Caveats.** Single seed; 3k-step short-train (machinery certification, not a
38
+ capability claim); one LoRA placement/rank; round-trip n=24. Cost ≈ 3.1 GPU-h.
39
+ Checkpoints: `relay_all16_s0.pt`, LoRA in the run dir (ships on request —
40
+ the relay stack is the line's artifact).
exp006_sd15core_relay/dexp006_sd15core_relay.py ADDED
@@ -0,0 +1,342 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """dexp006_sd15core_relay.py — exp006: relays on the CORE EPRED SD1.5.
2
+
3
+ Phil directive 2026-07-16: "the most powerful element is the epred variants of
4
+ the core sd15 and sdxl" (Lune = an undertrained exemplar). This is exp001's
5
+ design transplanted to the natural paradigm:
6
+ trunk — STOCK stable-diffusion-v1-5 UNet, fp32 (native release precision;
7
+ dtype law: adapters match).
8
+ objective — STANDARD epsilon prediction on the stock training schedule
9
+ (scaled_linear betas from the shipped scheduler config,
10
+ t ~ U{0..999}, target = noise).
11
+ cond — plain-English `prompt` column, STANDARD 77-token CLIP encode.
12
+ arms — frozen / relay_all16 / matched LoRA-r32 (identical cache, paired
13
+ val on FIXED per-row (noise, t), pure Adam wd=0).
14
+ judge — round-trip CLIP-L cond-vs-SHUFFLED via the standard
15
+ StableDiffusionPipeline (stock scheduler), read against
16
+ exp000b's sd15_epred_core baseline row.
17
+ gates — P-INIT/P-TOGGLE bit-exact incl. post-train; gate telemetry.
18
+
19
+ Prereg: relay >= lora on paired val eps-MSE at matched params; parity green;
20
+ gate means vs the 0.012-0.03 band (second non-LM reading). 1-seed CANDIDATE.
21
+ SDXL epred relay = the successor experiment (dual-encoder cond; after this
22
+ certifies).
23
+
24
+ Pod: bash pod2/run_exp006.sh [DEXP6_STEPS=3000 DEXP6_BATCH=16]
25
+ """
26
+ from __future__ import annotations
27
+
28
+ import io
29
+ import json
30
+ import os
31
+ import sys
32
+ import time
33
+
34
+ sys.path[:0] = ["pod2", "."]
35
+
36
+ import torch
37
+ import torch.nn.functional as F
38
+
39
+ from pod_ledger import ledger_run, note, burn_down
40
+ from aleph_diffusion_core import derangement, gate_stats, save_relay_stack
41
+ from d1_substrate import attach_relays, MEM_FRACTION
42
+
43
+ DATASET = "AbstractPhil/synthetic-object-relations-json"
44
+ SD_BASE = "stable-diffusion-v1-5/stable-diffusion-v1-5"
45
+ VAE_SCALE = 0.18215
46
+ N_TRAIN, N_VAL, N_JUDGE = 4096, 256, 24
47
+ BATCH = int(os.environ.get("DEXP6_BATCH", "16"))
48
+ STEPS = int(os.environ.get("DEXP6_STEPS", "3000"))
49
+ LR, CFG_DROPOUT, SEED = 1e-3, 0.1, 0
50
+ DATA_DIR = ("/workspace/data/dexp006" if os.path.isdir("/workspace")
51
+ else os.path.join(os.environ.get("GEOLIP_DATA", "./data"),
52
+ "dexp006"))
53
+ CKPT_DIR = ("/workspace/ckpts2/dexp006" if os.path.isdir("/workspace")
54
+ else DATA_DIR)
55
+
56
+
57
+ def encode_nl77(prompts, tok, te, device):
58
+ ids = tok(prompts, padding="max_length", max_length=tok.model_max_length,
59
+ truncation=True, return_tensors="pt").input_ids.to(device)
60
+ return te(ids)[0]
61
+
62
+
63
+ def build_cache(device="cuda"):
64
+ cache_f = os.path.join(DATA_DIR, "cache.pt")
65
+ if os.path.exists(cache_f):
66
+ print(f"[cache] exists: {cache_f}")
67
+ return cache_f
68
+ os.makedirs(DATA_DIR, exist_ok=True)
69
+ from PIL import Image
70
+ import numpy as np
71
+ from diffusers import AutoencoderKL
72
+ from transformers import CLIPTextModel, CLIPTokenizer
73
+ from dexp001_sd15_relay import _iter_rows
74
+ vae = AutoencoderKL.from_pretrained(
75
+ SD_BASE, subfolder="vae", torch_dtype=torch.float32).to(device).eval()
76
+ tok = CLIPTokenizer.from_pretrained(SD_BASE, subfolder="tokenizer")
77
+ te = CLIPTextModel.from_pretrained(
78
+ SD_BASE, subfolder="text_encoder",
79
+ torch_dtype=torch.float32).to(device).eval()
80
+ g = torch.Generator(device=device).manual_seed(SEED)
81
+ lat, ehs, buf_img, buf_txt = [], [], [], []
82
+
83
+ @torch.no_grad()
84
+ def flush():
85
+ if not buf_img:
86
+ return
87
+ px = torch.stack(buf_img).to(device)
88
+ lat.append((vae.encode(px).latent_dist.sample(generator=g)
89
+ * VAE_SCALE).cpu())
90
+ ehs.append(encode_nl77(buf_txt, tok, te, device).cpu())
91
+ buf_img.clear()
92
+ buf_txt.clear()
93
+
94
+ n = 0
95
+ for fname, r in _iter_rows(N_TRAIN + N_VAL):
96
+ img = r["image"]
97
+ img = img.get("bytes") if isinstance(img, dict) else img
98
+ im = Image.open(io.BytesIO(img)).convert("RGB").resize((512, 512))
99
+ buf_img.append(torch.from_numpy(np.asarray(im)).float()
100
+ .permute(2, 0, 1) / 127.5 - 1.0)
101
+ p = r["prompt"]
102
+ buf_txt.append(p if isinstance(p, str) else json.dumps(p))
103
+ n += 1
104
+ if len(buf_img) == 16:
105
+ flush()
106
+ if n % 512 == 0:
107
+ print(f"[cache] {n}/{N_TRAIN + N_VAL}", flush=True)
108
+ flush()
109
+ lat, ehs = torch.cat(lat), torch.cat(ehs)
110
+ gv = torch.Generator().manual_seed(SEED + 1)
111
+ val_noise = torch.randn(N_VAL, 4, 64, 64, generator=gv)
112
+ val_t = torch.randint(0, 1000, (N_VAL,), generator=gv)
113
+ torch.save({"lat": lat[:N_TRAIN], "ehs": ehs[:N_TRAIN],
114
+ "val_lat": lat[N_TRAIN:], "val_ehs": ehs[N_TRAIN:],
115
+ "val_noise": val_noise, "val_t": val_t}, cache_f)
116
+ print(f"[cache] built: train {N_TRAIN}, val {N_VAL} (nl77 cond)",
117
+ flush=True)
118
+ del vae, te
119
+ torch.cuda.empty_cache()
120
+ return cache_f
121
+
122
+
123
+ def make_schedule(device):
124
+ """Stock SD15 training schedule from the shipped scheduler config."""
125
+ from diffusers import DDPMScheduler
126
+ sch = DDPMScheduler.from_pretrained(SD_BASE, subfolder="scheduler")
127
+ assert sch.config.prediction_type == "epsilon", sch.config.prediction_type
128
+ return sch.alphas_cumprod.to(device)
129
+
130
+
131
+ def add_noise(lat, noise, t, acp):
132
+ a = acp[t].sqrt()[:, None, None, None]
133
+ s = (1 - acp[t]).sqrt()[:, None, None, None]
134
+ return a * lat + s * noise
135
+
136
+
137
+ def eps_loss(unet, lat, ehs, gen, acp, device):
138
+ bsz = lat.shape[0]
139
+ drop = torch.rand(bsz, generator=gen, device=device) < CFG_DROPOUT
140
+ ehs = ehs.clone()
141
+ ehs[drop] = 0
142
+ t = torch.randint(0, 1000, (bsz,), generator=gen, device=device)
143
+ noise = torch.randn(lat.shape, generator=gen, device=device)
144
+ pred = unet(add_noise(lat, noise, t, acp), t, ehs, return_dict=False)[0]
145
+ return F.mse_loss(pred, noise)
146
+
147
+
148
+ @torch.no_grad()
149
+ def val_mse(unet, cache, acp, device):
150
+ tot = []
151
+ for i in range(0, N_VAL, 32):
152
+ lat = cache["val_lat"][i:i + 32].to(device)
153
+ ehs = cache["val_ehs"][i:i + 32].to(device)
154
+ noise = cache["val_noise"][i:i + 32].to(device)
155
+ t = cache["val_t"][i:i + 32].to(device)
156
+ pred = unet(add_noise(lat, noise, t, acp), t, ehs,
157
+ return_dict=False)[0]
158
+ tot += ((pred - noise) ** 2).mean(dim=(1, 2, 3)).tolist()
159
+ return sum(tot) / len(tot)
160
+
161
+
162
+ @torch.no_grad()
163
+ def round_trip(unet, device):
164
+ """Standard-pipeline round trip (stock scheduler) on the exp000 rows."""
165
+ from d1_exp000b_natural import load_rows
166
+ from d1_exp000_baselines import judge_selftest
167
+ from diffusers import StableDiffusionPipeline
168
+ from transformers import CLIPModel, CLIPProcessor
169
+ from PIL import Image
170
+ rows = load_rows(N_JUDGE)
171
+ clip = CLIPModel.from_pretrained(
172
+ "openai/clip-vit-large-patch14",
173
+ torch_dtype=torch.float32).to(device).eval()
174
+ cproc = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")
175
+ feat = judge_selftest(clip, cproc, device)
176
+ orig = torch.cat([
177
+ feat(Image.open(io.BytesIO(r["image_bytes"])).convert("RGB"))
178
+ for r in rows])
179
+ prompts = [r["prompt"] for r in rows]
180
+ perm = derangement(N_JUDGE, seed=1234)
181
+ pipe = StableDiffusionPipeline.from_pretrained(
182
+ SD_BASE, unet=unet, torch_dtype=torch.float32,
183
+ safety_checker=None).to(device)
184
+ out = {}
185
+ for arm, ps in (("cond", prompts),
186
+ ("shuffled", [prompts[i] for i in perm.tolist()])):
187
+ cos = []
188
+ for i in range(0, N_JUDGE, 4):
189
+ g = torch.Generator(device=device).manual_seed(1234 + i)
190
+ imgs = pipe(ps[i:i + 4], num_inference_steps=30,
191
+ generator=g).images
192
+ f = torch.cat([feat(p) for p in imgs])
193
+ cos += (f * orig[i:i + len(imgs)]).sum(-1).tolist()
194
+ out[arm] = round(sum(cos) / len(cos), 4)
195
+ out["cond_minus_shuffled"] = round(out["cond"] - out["shuffled"], 4)
196
+ del pipe, clip
197
+ torch.cuda.empty_cache()
198
+ return out
199
+
200
+
201
+ def load_unet(device):
202
+ from diffusers import UNet2DConditionModel
203
+ unet = UNet2DConditionModel.from_pretrained(
204
+ SD_BASE, subfolder="unet", torch_dtype=torch.float32).to(device)
205
+ unet.requires_grad_(False)
206
+ unet.eval()
207
+ unet.enable_gradient_checkpointing()
208
+ return unet
209
+
210
+
211
+ def train_loop(unet, params, cache, acp, device, label):
212
+ opt = torch.optim.Adam(params, lr=LR, weight_decay=0.0)
213
+ gen = torch.Generator(device=device).manual_seed(SEED + 42)
214
+ idx_gen = torch.Generator().manual_seed(SEED + 7)
215
+ torch.cuda.reset_peak_memory_stats()
216
+ t0, losses = time.time(), []
217
+ for step in range(1, STEPS + 1):
218
+ sel = torch.randint(0, N_TRAIN, (BATCH,), generator=idx_gen)
219
+ loss = eps_loss(unet, cache["lat"][sel].to(device),
220
+ cache["ehs"][sel].to(device), gen, acp, device)
221
+ loss.backward()
222
+ opt.step()
223
+ opt.zero_grad(set_to_none=True)
224
+ losses.append(loss.item())
225
+ if step == 50 or step % 500 == 0:
226
+ print(f"[{label}] step {step}: loss {loss.item():.4f} | "
227
+ f"{(time.time() - t0) / step:.2f}s/step | peak "
228
+ f"{torch.cuda.max_memory_allocated() / 2**30:.1f}GB",
229
+ flush=True)
230
+ return {"steps": STEPS,
231
+ "final_loss_ma50": round(sum(losses[-50:]) / 50, 5),
232
+ "s_per_step": round((time.time() - t0) / STEPS, 3),
233
+ "peak_mem_gb":
234
+ round(torch.cuda.max_memory_allocated() / 2**30, 2)}
235
+
236
+
237
+ def run(device="cuda"):
238
+ torch.cuda.set_per_process_memory_fraction(MEM_FRACTION, 0)
239
+ os.makedirs(CKPT_DIR, exist_ok=True)
240
+ acp = make_schedule(device)
241
+ results = {"config": {"steps": STEPS, "batch": BATCH, "lr": LR,
242
+ "seed": SEED, "objective": "epsilon (stock schedule)",
243
+ "cond": "nl77", "optimizer": "torch.optim.Adam wd=0"}}
244
+ with ledger_run("dexp006 cache build", budget_h=0.5):
245
+ build_cache(device)
246
+ cache = torch.load(os.path.join(DATA_DIR, "cache.pt"),
247
+ map_location="cpu", weights_only=True)
248
+
249
+ with ledger_run("dexp006 frozen reference", budget_h=0.2) as h:
250
+ unet = load_unet(device)
251
+ results["frozen"] = {"val": val_mse(unet, cache, acp, device)}
252
+ del unet
253
+ torch.cuda.empty_cache()
254
+ h["verdict"] = f"val {results['frozen']['val']:.5f}"
255
+
256
+ with ledger_run("dexp006 relay_all16 s0", budget_h=2.5) as h:
257
+ unet = load_unet(device)
258
+ relays, _ = attach_relays(unet)
259
+ n_params = sum(p.numel() for p in relays.parameters())
260
+ print(f"[relay] {len(relays)} sites, {n_params:,} trainable "
261
+ f"(dtype {next(relays.parameters()).dtype})", flush=True)
262
+ for rl in relays:
263
+ rl.train()
264
+ stats = train_loop(unet, relays.parameters(), cache, acp, device,
265
+ "relay")
266
+ for rl in relays:
267
+ rl.eval()
268
+ v_on = val_mse(unet, cache, acp, device)
269
+ for rl in relays:
270
+ rl.enabled = False
271
+ v_off = val_mse(unet, cache, acp, device)
272
+ d = abs(v_off - results["frozen"]["val"])
273
+ assert d < 1e-9, f"post-train toggle parity broken: {d}"
274
+ for rl in relays:
275
+ rl.enabled = True
276
+ save_relay_stack(relays, os.path.join(CKPT_DIR, "relay_all16_s0.pt"))
277
+ rt = round_trip(unet, device)
278
+ results["relay_all16"] = {"n_params": n_params, "train": stats,
279
+ "val": v_on, "val_toggled_off": v_off,
280
+ "gates": gate_stats(relays),
281
+ "round_trip": rt}
282
+ del unet, relays
283
+ torch.cuda.empty_cache()
284
+ h["verdict"] = f"val {v_on:.5f} rt {rt['cond_minus_shuffled']:+.4f}"
285
+
286
+ with ledger_run("dexp006 lora_r32 s0", budget_h=2.5) as h:
287
+ from peft import LoraConfig, get_peft_model
288
+ unet = load_unet(device)
289
+ targets = [n for n, m in unet.named_modules()
290
+ if isinstance(m, torch.nn.Linear) and "attn2" in n
291
+ and (n.split(".")[-1] in ("to_q", "to_k", "to_v")
292
+ or n.endswith("to_out.0"))]
293
+ unet = get_peft_model(unet, LoraConfig(r=32, lora_alpha=32,
294
+ target_modules=targets))
295
+ params = [p for p in unet.parameters() if p.requires_grad]
296
+ n_params = sum(p.numel() for p in params)
297
+ print(f"[lora] r=32 on {len(targets)} linears, {n_params:,}",
298
+ flush=True)
299
+ unet.train()
300
+ stats = train_loop(unet, params, cache, acp, device, "lora")
301
+ unet.eval()
302
+ v = val_mse(unet, cache, acp, device)
303
+ unet.save_pretrained(os.path.join(CKPT_DIR, "lora_r32_s0"))
304
+ base = unet.get_base_model() if hasattr(unet, "get_base_model") \
305
+ else unet
306
+ rt = round_trip(base, device)
307
+ results["lora_r32"] = {"n_params": n_params, "train": stats,
308
+ "val": v, "round_trip": rt}
309
+ del unet
310
+ torch.cuda.empty_cache()
311
+ h["verdict"] = f"val {v:.5f} rt {rt['cond_minus_shuffled']:+.4f}"
312
+
313
+ rv, lv = results["relay_all16"]["val"], results["lora_r32"]["val"]
314
+ results["verdict"] = {
315
+ "relay_beats_frozen": rv < results["frozen"]["val"],
316
+ "relay_vs_lora": "relay" if rv <= lv else "lora",
317
+ "param_ratio": round(results["relay_all16"]["n_params"]
318
+ / results["lora_r32"]["n_params"], 3),
319
+ "note": "core epred substrate; prereg relay >= lora; 1-seed CANDIDATE",
320
+ }
321
+ with open(os.path.join(DATA_DIR, "results.json"), "w") as f:
322
+ json.dump(results, f, indent=2)
323
+ note(f"dexp006 verdict: {json.dumps(results['verdict'])}")
324
+ print(json.dumps(results["verdict"], indent=2))
325
+ burn_down()
326
+ return results
327
+
328
+
329
+ def smoke():
330
+ assert STEPS > 0
331
+ acp_like = torch.linspace(0.9999, 0.05, 1000)
332
+ x = add_noise(torch.zeros(2, 4, 8, 8), torch.ones(2, 4, 8, 8),
333
+ torch.tensor([0, 999]), acp_like)
334
+ assert x[0].mean() < x[1].mean() # more noise at high t
335
+ print("dexp006 smoke PASSED (parse + schedule shape; GPU run is pod work)")
336
+
337
+
338
+ if __name__ == "__main__":
339
+ if "--run" in sys.argv:
340
+ run()
341
+ else:
342
+ smoke()
exp006_sd15core_relay/relay_all16_s0.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b2a69f7befcb8171b14e7fa56c4cbec33181830b566355ada25835dba6f850ac
3
+ size 12979593
exp006_sd15core_relay/results.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "config": {
3
+ "steps": 3000,
4
+ "batch": 16,
5
+ "lr": 0.001,
6
+ "seed": 0,
7
+ "objective": "epsilon (stock schedule)",
8
+ "cond": "nl77",
9
+ "optimizer": "torch.optim.Adam wd=0"
10
+ },
11
+ "frozen": {
12
+ "val": 0.1247876692286809
13
+ },
14
+ "relay_all16": {
15
+ "n_params": 3227568,
16
+ "train": {
17
+ "steps": 3000,
18
+ "final_loss_ma50": 0.10553,
19
+ "s_per_step": 1.816,
20
+ "peak_mem_gb": 11.17
21
+ },
22
+ "val": 0.12169808566522988,
23
+ "val_toggled_off": 0.1247876692286809,
24
+ "gates": {
25
+ "gate_mean": 0.07003,
26
+ "gate_min": 0.03646,
27
+ "gate_max": 0.09857
28
+ },
29
+ "round_trip": {
30
+ "cond": 0.7809,
31
+ "shuffled": 0.5637,
32
+ "cond_minus_shuffled": 0.2172
33
+ }
34
+ },
35
+ "lora_r32": {
36
+ "n_params": 3182592,
37
+ "train": {
38
+ "steps": 3000,
39
+ "final_loss_ma50": 0.10699,
40
+ "s_per_step": 1.635,
41
+ "peak_mem_gb": 10.08
42
+ },
43
+ "val": 0.12267412961273294,
44
+ "round_trip": {
45
+ "cond": 0.736,
46
+ "shuffled": 0.5764,
47
+ "cond_minus_shuffled": 0.1596
48
+ }
49
+ },
50
+ "verdict": {
51
+ "relay_beats_frozen": true,
52
+ "relay_vs_lora": "relay",
53
+ "param_ratio": 1.014,
54
+ "note": "core epred substrate; prereg relay >= lora; 1-seed CANDIDATE"
55
+ }
56
+ }