Dancing Stick Figures — baseline checkpoints (v0.1)
Reference models trained on sprited/dancing-stick-figures
with the code in https://github.com/sprited-ai/dancing-stick-figures. All unconditional, RGBA, EMA weights included,
optimizer state stripped. Load with the trainers' --init (warm-start) or --resume, or with eval/score_images.py.
| file | arch | res | steps | recipe | oracle tvr / lie / clean (floor) |
|---|---|---|---|---|---|
unet_img64.pt |
factorised UNet 46 M, v-pred, min-SNR-5 | 64² | 100k | batch 128, cosine→2 % | .134 / .116 / .43 (.136 / .103 / .40) |
dit_img64_p2.pt |
DiT-FM 33 M, patch 2 | 64² | 50k | batch 128, logit-normal t | .164 / .114 / .40 (.139 / .106 / .37) |
unet_img64_30k.pt |
UNet | 64² | 30k | plain MSE | .159 / .113 / .42 |
dit_img64_p4_30k.pt |
DiT-FM patch 4 | 64² | 30k | .176 / .122 / .38 | |
unet_img128.pt |
UNet, min-SNR-5 | 128² | 20k | batch 128 | .226 / .073 / .22 (.203 / .047 / .23) |
dit_img128_p4.pt |
DiT-FM patch 4 | 128² | 40k | batch 128 | .251 / .065 / .23 (.209 / .048 / .21) |
Video (64² × 8 frames @ 20 fps, UNet 46 M, batch 16, unconditional) — finished runs. Oracle on 64 samples × 2 seeds vs 64 real 8-frame windows (floor); FVD with a frame-repeated I3D (real-vs-real ≈ 110–120 in this setup):
| file | init | steps | tvr↓ | lie↓ | head-jitter↓ | angle-jerk↓ | FVD↓ |
|---|---|---|---|---|---|---|---|
unet_vid64_scratch.pt |
random | 85k | .171 | .101 | .40 | .125 | 199 |
unet_vid64_from_img.pt |
unet_img64.pt |
61k | .154 | .115 | .41 | .129 | 213 |
| real windows (floor) | — | — | .13 | .09–.11 | .32–.36 | .077 | 110–120 |
Read: warm-starting from the image model gets there ~2.5× sooner (loss at 4k ≈ scratch at 10k) but ends in the same place — a
convergence-speed win, not a quality win. Per-frame anatomy is within ~0.03 of real frames; temporal jitter ~1.2× real; FVD ~80–100
above the real-vs-real floor. Sample GIFs: unet_vid64_scratch_samples.gif, unet_vid64_from_img_samples.gif.
Autoregressive video (the route's step 4) — unet_ar64.pt: same UNet, --ar_ctx 8 --frames 8 --stride 2 (8 context + 8 new
frames per chunk, 10 fps), initialised from unet_img64.pt, 60k steps on one H100 (batch 16, ~5.5 h). Rolls out to any length:
python scripts/rollout.py --ckpt unet_ar64.pt --seconds 5. Oracle on 32 five-second rollouts vs 32 real 5 s clips —
tvr .149 / .128, lie .121 / .103, head-jitter .69 / .57, angle-jerk .19 / .14 (model / real). unet_ar64_rollout.gif = 8 samples × 5.6 s.
unet_ar64_interim.pt = the same run at 30k.
DiT track (interim, stopped at 44k/42k of 61k): dit_vid64_from_img_interim.pt (init from dit_img64_p2.pt, patch 2, shift 2, 10 % image
batches, 20 % I2V) and dit_vid64_scratch_interim.pt; class-conditional image models: unet_img64_cond.pt, dit_img64_p2_cond.pt (5 prompt groups, CFG).
Compare your model against these in one command:
python scripts/compare.py --ckpt runs/img64/ckpt.pt --cache data/cache --ref unet_img64 # image models
python -m eval.run_ckpt --run runs/vid64 --cache data/cache --n 64 # video: temporal oracle + FVD
# warm-start a video model from the image model (Seedance-style stage 2)
hf download sprited/dancing-stick-figures-baselines unet_img64.pt --local-dir ckpts
python -m train.video_ddpm --cache data/cache --out runs/vid64i --size 64 --frames 8 --batch 16 --init ckpts/unet_img64.pt --fast --compile
# sample + score an image model
python -m eval.score_images --ckpt ckpts/unet_img64.pt --cache data/cache --n 512 --grid out/grid.png
Checkpoint dict: {"ema": state_dict, "model": state_dict, "step": int, "args": dict, "groups": [...], "arch": "unet"|"dit_fm"}.