File size: 2,671 Bytes
f065e53 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | """FULL SMOKE for SpatialDiffuseSlot:
1. tok_L init loads: encoder 100%, DiT trunk (except null_cond K-mismatch)
2. training forward: diff_loss + repa_loss finite
3. backward: pool/cond-embedder grads flow; frozen DiT trunk has no grads
4. mask actually in play (spatial_mask buffer on the rebuilt DiT)
CPU, small batch. Catches integration bugs before GPU run.
"""
import torch
from omegaconf import OmegaConf
from semanticist.stage1.spatial_diffuse_slot import SpatialDiffuseSlot
torch.manual_seed(0)
cfg = OmegaConf.load("configs/tokenizer_l.yaml")
p = dict(cfg["trainer"]["params"]["model"]["params"])
p.pop("ckpt_path", None)
# keep num_slots=256 (encoder ckpt-exact); DiT rebuilt at 85 internally
m = SpatialDiffuseSlot(freeze_dit=True, pool_depth=2, **p)
ck = torch.load("../new_eval_spatial_reasoning0430/eval_assets/semanticist_pretrained/semanticist_tok_L.pkl", map_location="cpu")
ck = {k.replace("._orig_mod", ""): v for k, v in ck.items()}
# BUG FOUND & FIXED: strict=False still ERRORS on shape mismatch. tok_L's
# null_cond is (1,256,16) but ours is (1,85,16) -> drop it (fresh init).
ck.pop("dit.null_cond", None)
ret = m.load_state_dict(ck, strict=False)
enc_missing = [k for k in ret.missing_keys if k.startswith("encoder.")]
dit_missing = [k for k in ret.missing_keys if k.startswith("dit.") and "null_cond" not in k and "pos_embed" not in k]
print(f"[init] encoder missing={len(enc_missing)} (0 expected) | dit trunk missing={len(dit_missing)} (0 expected)")
print(f"[init] null_cond shape={tuple(m.dit.null_cond.shape)} (1,85,16 expected)")
assert len(enc_missing) == 0 and len(dit_missing) == 0
assert tuple(m.dit.null_cond.shape) == (1, 85, 16)
assert m.dit.spatial_mask.shape == (64 + 85, 64 + 85)
# ---- training forward (tiny batch, CPU) ----
m.train()
x = torch.randn(2, 3, 256, 256)
losses = m(x, sample=False)
print("[fwd] losses:", {k: float(v) for k, v in losses.items()})
total = sum(losses.values())
assert torch.isfinite(total)
# ---- backward: trainable = pool + cond embedder + null_cond (+encoder/enc2slot) ----
total.backward()
def gnorm(mod):
s = 0.0
for q in mod.parameters():
if q.grad is not None:
s += q.grad.norm().item() ** 2
return s ** 0.5
g_pool = gnorm(m.spatial_pool)
g_emb = gnorm(m.dit.autoenc_cond_embedder)
g_trunk = sum((q.grad is not None and q.grad.abs().sum().item() > 0) for n, q in m.dit.named_parameters() if n.startswith("blocks."))
print(f"[bwd] grad-norm pool={g_pool:.4f} cond_embedder={g_emb:.4f} | frozen-trunk grads={g_trunk} (0 expected)")
assert g_pool > 0 and g_emb > 0 and g_trunk == 0
print("FULL SMOKE PASSED ✅ init/forward/backward/freeze all correct")
|