Anima 蒸留 — 実走で分かった知見
TL;DR: 数万円予算で Anima を自前 SOTA 蒸留(DMD2+TSCD+R3GAN)するのは 現実的に困難。5 回失敗で累計 $165。実用解は
merge_turbo_lora(公式 Anima Turbo LoRA との合成、$0.5、即動く)。自前で挑む人向けに、 何が起きるか・なぜ難しいかを以下に集約。2026-05 以降の改善試行 (PCM / LADD / Reflow など既存実装の移植) は migration_log.md を参照。
1. 概要(結論先出し)
このリポジトリでは Anima(CircleStone Labs, Cosmos-Predict2 派生 2B DiT)を Decoupled DMD2 + TSCD + R3GAN で step 削減蒸留 することを目指した。 B200 GPU(Modal)で 5000 枚 self-distillation データセットを使い、計 5 回の失敗:
| 試行 | 構成 | 結果 | コスト |
|---|---|---|---|
| Phase A | full DiT, R3GAN gamma=50 | 完全ノイズ(D 爆発) | $70 |
| Phase B v1 | Q,V LoRA, R3GAN OFF | 緑色化(AdaLN 不触) | $10 |
| Phase B v2 | wide LoRA, R3GAN OFF | mean collapse | $10 |
| Phase B v3a | wide LoRA, gamma=0.1 | step 30 で D 爆発 abort | $5 |
| Phase B v3b | wide LoRA, gamma=1.0 | mean collapse + 後で D 爆発 | $20 |
最終理解: R3GAN は「D 爆発」と「無信号 → mean collapse」の間に 安定 zone が 極めて狭く、Anima latent(16ch × 128²)で持続的な訓練は現状の構成では困難。 DMDR / Z-Image の公式実装が DINOv2 reward に依存 していることからも、 adv loss 単独の R3GAN だけでは Anima 系の蒸留は厳しい可能性が高い。
1.1 結局どうすればいいか
| 用途 | 推奨パス | コスト | 結果 |
|---|---|---|---|
| すぐ 8-12 step 推論したい | merge_turbo_lora(公式 Civitai Turbo LoRA を Anima base に重ねる) |
$0.5 | ✅ 即動く、CFG=1 / 8-12 step |
| どうしても自前で蒸留したい | 本ドキュメントの試行錯誤を踏まえ、DINOv2 reward 切替 等を追加実装 | +$50-100 + 開発時間数日 | △ 未検証 |
| 学習目的・記録目的 | 本ドキュメントを読む | $0 | 知見だけ |
強い推奨: 商用要件がなければ
merge_turbo_loraで十分。CircleStone Labs 自身が遥かに多い計算資源と試行錯誤の上で作った Turbo LoRA が既に Civitai にある(https://civitai.com/models/2560840)、これに勝つのは数万円では困難。
2. 結局成功した実用パス: merge_turbo_lora
# 1. Anima Turbo LoRA を Civitai からダウンロード
modal run modal_app.py::download_civitai_lora # version_id=2877687 がデフォルト
# 2. (任意) 自前 Phase 1 LoRA とマージ(なくても可)
modal run modal_app.py::merge_turbo_lora
# 3. ComfyUI で base + LoRA(strength=1.0)を組み、8 step CFG=1 で生成
実装: modal_app.py::download_civitai_lora, merge_turbo_lora, stage_lora_to_models。
ComfyUI workflow は scripts/anima_workflow_turbo.json 参照。
実測の Turbo LoRA 出力品質: base 30 step CFG=4.5 と同等のキャラクター品質を
8 step CFG=1 で達成(検証画像は /dataset/compare/turbo_8step/ に保存)。
3. 自前 SOTA 蒸留(本リポジトリで実装、未完成)
scripts/distill/ に Decoupled DMD2 + TSCD + R3GAN を実装。コード自体は動く が、
ハイパーパラメータの調整で 5 回失敗。以下「我々が試した推奨設定」だが、これでも
2000 step で失敗 — これから挑む人は次節 §4 §5 を読んでから。
3.1 試した(が安定しなかった)設定
=== モデル / データ ===
base model: Anima preview3-base (Cosmos-Predict2 派生)
text encoder: Qwen3-0.6B + LLM Adapter (T5 空間ブリッジ)
VAE: WanVAE (16-channel latent, scale=[mean, 1/std])
dataset: self-distillation 5000 枚(base が 30 step CFG 4.5 で生成)
解像度 1024px 周辺の 7 種 aspect ratio をランダム
=== 学習 (LoRA-only) ===
trainable: gen + guidance ともに LoRA、base は frozen
gen LoRA: **wide** (all-linear except llm_adapter), rank=32
→ AdaLN modulation を含む全 Linear に attach
guidance LoRA: Q,V LoRA, rank=32 (DMDR 互換、軽量)
optimizer: gen / guidance: AdamW lr=2e-5 β=(0.9, 0.999) wd=0.01
D: Adam lr=2e-4 β=(0, 0.99) (StyleGAN 流)
grad clip: 1.0
=== Loss 構成 ===
L_dmd: DMDR gradient trick (p_real - p_fake) / norm
L_consist: TSCD MSE vs EMA generator (decay=0.999)
L_adv (gen): R3GAN relativistic RpGAN, weight=0.05
L_disc: R3GAN softplus + γ/2 · (R1 + R2)
γ = 0.05〜0.5 (grid search 必須)
=== 更新比率 / スケジュール ===
guidance update: 5 回 / outer step
generator update: 1 回 / outer step
discriminator: 1 回 / outer step
CFG Augmentation: real_score を cfg=2.0 で評価 (cold_start 100 step は cfg=0)
dynamic LoRA r: real-side scale を cosine で 0 に decay (decay_steps=2000)
=== Phase 構成 ===
Phase B: base 直接 + wide LoRA, num_inference_steps=4, 2000 step
Phase C: Phase B から resume または base 直接, wide LoRA, num_steps=2, 2000 step
※ Full DiT 訓練 (Phase A) は不要 — LoRA-only で十分
=== Sanity / Guard ===
sanity test: 200 step + 中間生成 1 枚で degeneration 検出
abort guards: d_r1 > 1000 / d_r2 > 1000 / loss > 1e6
checkpoint: 500 step 毎 + 都度 volume.commit()
PYTHONUNBUFFERED=1 + cwd=/workspace/diffusion-pipe
=== Modal infra ===
GPU: B200 (192GB) — LoRA-only で余裕、batch=4
image: CUDA 12.4 + Python 3.11 + diffusion-pipe + torchvision
volumes: anima-models / anima-dataset / anima-outputs
secrets: hf_token, civitai_api_key
=== ComfyUI 出力形式 ===
LoRA key: diffusion_model.<module>.lora_A.weight / .lora_B.weight
(PEFT の base_model.model.<...>.lora_A.default.weight から変換)
基底 ckpt: anima ckpt 系は net. prefix 必須 (ComfyUI が arch 検出に使う)
実装は scripts/distill/ + modal_app.py::train_sota_distill を参照。
⚠️ 重要: 上の設定で 2000 step training を 5 回試したが、いずれも失敗。 Anima latent では R3GAN の安定 zone が極めて狭く、長期持続が困難だった。 これから挑む人は §4(全失敗の詳細)+ §5(残された改善方向)を必ず読むこと。
3.2.1 なぜ LoRA-only(full DiT 訓練ではなく)
| full DiT(Phase A) | LoRA-only(Phase B/C) | |
|---|---|---|
| trainable params | 2B | 30-150M |
| step 時間 (B200) | 14 秒 | 2.8-3.0 秒(5x 速) |
| 出力 | 4 GiB ckpt | 30-150 MiB LoRA |
| 配布性 | 他 FT と排他 | 他 LoRA とスタック可 |
| optimizer state | 8 GB | ~200 MB |
| failure 局所化 | base 全体破壊リスク | LoRA だけ |
Anima のように既に高品質な base を蒸留する場合、LoRA-only がコスト・配布性・ 安全性のすべてで優位。Phase A 流の full DiT 訓練は不要だった。
3.2.2 なぜ「wide LoRA」(Q,V LoRA ではなく)
Anima/Cosmos の DiT は AdaLN modulation で timestep 情報を処理する架構:
block(x, t):
t_embed = t_embedder(t)
# AdaLN modulation = block_input をどう変調するかを timestep から決める
scale, shift, gate = adaln_modulation(t_embed) ← ここが timestep の入り口
x = LayerNorm(x) * (1 + scale) + shift
x = x + gate * attention(x, ...)
蒸留とは「timestep の解釈を変える」こと(少ない step でも denoise しきる)。 それには adaln_modulation の Linear を学習対象に含める必要がある。Q,V LoRA だと attention pattern だけ変えられて timestep 入り口を触れない → 学習が degenerate な「色 / スタイル shift」に逃げる(Phase B v1 の緑色化はこれ)。
公式 Anima Turbo LoRA も同じ理由で adaln_modulation を target(1016 keys、 我々の wide LoRA 980 keys とほぼ同等)。
3.2.3 なぜ R3GAN が必要(adv loss なしではダメ)
DMD2 単体は mean collapse に陥る(Phase B v2 で実証)。理由:
- DMD gradient
(real_score - fake_score)は「real distribution の方向」を示す - LoRA capacity が大きいほど、「real の mean を出力するのが最も安全」という解に収束しやすい
- TSCD(EMA self との consistency)は collapse を加速こそすれ防げない
R3GAN(または同等の adv / reward 信号)があると:
- D が「real は sharp、fake は blurry」と学習
- gen は「blurry な mean を出すと D に見抜かれる」と分かり、sharp な多様性を保つ
- これが mean collapse の唯一の防御策
実際、DMD2 / Hyper-SD / DMDR 系の全公式実装で adv loss(or reward loss)が必須。
3.2.4 なぜ R3GAN gamma の grid search が必須
R3GAN の R1+R2 gradient penalty 重み gamma は 入力空間のスケールに比例:
| ドメイン | 入力 channel | 解像度 | gamma |
|---|---|---|---|
| CIFAR-10 | 3 | 32x32 | 0.05 |
| FFHQ-64 | 3 | 64x64 | 2 |
| FFHQ-256 | 3 | 256x256 | 150 |
| Anima latent | 16 | 128x128 | ~0.05-1(grid search 必須) |
Anima latent は per-sample 262k 要素で、典型 pixel 空間より gradient norm が 大きい → gamma は数値が小さくないと penalty が爆発。Phase A は gamma=50 で 500x 過大 にしたら discriminator が崩壊した(詳細は §4 Phase A 参照)。
3.2.5 なぜ guard rail(d_r1/r2 > 1000 で abort)
Phase A は loss は全部健全に推移(l_dmd 0.005, l_adv_g 0.69 で一定)しつつ
裏で discriminator gradient が爆発し、completed ckpt が完全ノイズ出力という
ステルス失敗。後付けの分析で「step 1500 時点 d_r1 ~700 / step 2300 で 500k」と
わかったため、しきい値 1000 で abort すれば即停止できる。
しきい値 1000 の根拠: 正常上限 ~100 の 10x、致命傷 500k の 1/500 で、確実に ステルス damage が始まる前に止まる。
3.2.6 なぜ Decoupled DMD2 + TSCD(LCM / Hyper-SD ではなく)
| 手法 | 性質 | 我々の選択理由 |
|---|---|---|
| LCM | consistency 単体、シンプル | low-step 品質に限界 |
| Hyper-SD | TSCD + adv、segment-wise progressive | gamma calibration 必要、参照実装 SDXL only |
| DMD2 / DMDR | 分布マッチング + adv、Anima のような flow matching DiT に最適 | Z-Image(Cosmos 派生)で実証済、適応容易 |
DMD2 系は flow matching ベース(Anima の rectified flow と同じ) で、math 変換不要なのが決定打。TSCD は Hyper-SD から借りた多 step 一貫性で、純粋 DMD2 の単 step 偏りを補正。
3.2.7 なぜ 5000 枚 self-distillation データセット
| データソース | コスト | 利点 | 欠点 |
|---|---|---|---|
| Anima 自己生成 | $44 (10 B200 並列 40min) | base の出力分布に最適化 / ライセンス問題なし | base の癖をそのまま継承 |
| Danbooru / Pixiv | $0 + キュレーション時間 | 多様性 | ライセンス・タグ品質ばらつき |
| 公開データセット(LAION 等) | $0 + DL コスト | 多様性最大 | アニメ系少ない |
蒸留の本質は「base と同じ出力を低 step で」なので、self-distillation で 分布を base に一致させるのが理論的に正しい(distillation の定義)。
3.2.8 なぜ B200(H100 / A100 ではなく)
| GPU | Modal $/h | LoRA-only step 時間 | 192GB VRAM の意味 |
|---|---|---|---|
| A100-80GB | $2.50 | 7-9 秒 | OOM 危険、batch=1 |
| H100-80GB | $3.95 | 4-6 秒 | OOM 危険、batch=1-2 |
| B200 | $6.25 | 2.8-3.0 秒 | 3 model 同時 + batch=4-8 余裕 |
B200 の per-hour 単価は高いが、3 model(real/fake/gen)同時+batch 増で 実質的な per-experiment コストは最安。R3GAN を入れても OOM 不安なし。
4. 実際の失敗(全 5 件、詳細)
| # | 試行 | 構成 | 結果 | 累計 |
|---|---|---|---|---|
| 1 | Phase A | full DiT + Q,V LoRA, R3GAN γ=50, 3000 step | 完全ノイズ(D 爆発) | $70 |
| 2 | Phase B v1 | Q,V LoRA, R3GAN OFF, 2000 step | 緑色化(AdaLN 不触) | $80 |
| 3 | Phase B v2 | wide LoRA, R3GAN OFF, 2000 step | mean collapse(灰緑平面) | $90 |
| 4 | Phase B v3a | wide LoRA, R3GAN γ=0.1, 2000 step | step 30 で d_r1=1648 → abort | $95 |
| 5 | Phase B v3b | wide LoRA, R3GAN γ=1.0, 2000 step | 早期 mean collapse → 後半 D 爆発 | $115 |
各失敗が 異なる failure mode で起きた点が重要。「1 つ直しても他で詰まる」 直交性が、SOTA 蒸留を Anima 系で安定させる難しさの本質。
4.1 Phase A の詳細 postmortem(5 層因果分析)
ステルス失敗: 訓練ログ上は全 loss 健全(l_dmd 0.003-0.008, l_adv_g 0.69 一定)
だったのに、完走 ckpt が完全ノイズ出力。原因は 5 層の連鎖:
Layer 1 — gamma calibration ミス(根本)
- Anima latent(16ch × 128x128)に対し gamma=50 は 50-500 倍過大
- Agent リサーチが「latent norm 用 grid search 必須」と明示警告していたが、 手抜きで推測値を採用したのが発端
Layer 2 — R3GAN gradient が gen に流入(見えない damage)
l_adv_g = softplus(-(d_fake - d_real)) ≈ log 2 = 0.6914 ← 中立点
l_adv_g が一定で「adv 信号効いてない」と誤読。しかし gradient norm は別物:
∂L_adv_g/∂gen_output = (sigmoid 微分 ~0.5) · ∂(D の全層 Jacobian)
D 重みが gamma penalty 最小化で異常拡大 → D の Jacobian 爆発 → gen に流れる gradient が正常時の 数百〜数千倍。adv_weight=0.05 で抑えても scale 負け。
教訓: adv_loss の絶対値だけ見て安全と判断するな。gradient norm を別途モニタ。
Layer 3 — D 自体の破滅スパイラル
最初: l_disc = 0.69 + 25·0 = 0.69
膨張後: l_disc = 0.69 + 25·600,000 = 15,000,000
gamma が大きすぎて R1+R2 penalty 項が adv 項を支配 → D は adv 学習する余地なく、 ひたすら penalty 最小化に動く → ある瞬間 scale 崩れて d_r1/r2 が指数的に膨張。
Layer 4 — Sanity test の見落とし
- 50 step では destabilization が緩やかすぎて d_r1/r2 が正常範囲
- 本番 step 500-1000 から急速悪化
- 後から見れば step 1000 で d_r1/r2 が 100 超え始めていた($50 救えた)
教訓: Sanity は 200-500 step に延長。緩慢な発散も検出可能に。
Layer 5 — 監視/アラート不足
- d_r1/r2 はログ出していたが しきい値アラート未実装
- NaN/Inf check はあったが「大きすぎる値」検出なし
- gen の weight L2 norm を時系列で見れば damage 早期検出可能だった
- 中間 ckpt 毎の自動生成テストも未実装
修正後の guard rail(実装済):
# scripts/distill/dmd2_trainer.py
if d_r1 > 1000.0 or d_r2 > 1000.0:
raise RuntimeError(f"R3GAN penalty exploded (r1={d_r1:.1f}, r2={d_r2:.1f}). "
f"Reduce r3gan_gamma. Aborting.")
Phase A から学んだ悪設計のチェックリスト
| 問題 | 影響 |
|---|---|
| gamma を grid search せず推測 | 50-500 倍ズレ |
| adv_weight=0.05 で「安全装置」になると誤解 | gradient norm は別軸、効かなかった |
| sanity 50 step だけで本番投入 | 緩慢な発散見逃し |
d_r1/r2 にアラートしない |
早期 abort 機会逸失 |
| 中間 ckpt で部分検証しなかった | 完走してから初めて発覚($70 ロス) |
4.2 Phase B v1 — Q,V LoRA だと AdaLN を触れない
R3GAN を外して安全側に振った構成。loss は 0.02-0.03 で安定したが、生成すると 緑色化した anime キャラ。LoRA strength を 1.0 → 0.3 に下げると base に戻る (= LoRA は「均一に緑方向に押している」)。
原因: Q,V LoRA は cross-attention / self-attention の query / value だけを変更。 timestep modulation の入り口である AdaLN modulation Linear を触れない。 DiT が「少ない step でちゃんと denoise する」ために必要な timestep 解釈の変更が できず、勾配が attention の color / style shift に逃げて degenerate に収束。
→ 解決: LoRA target を 「AdaLN + attention + MLP の全 Linear」(wide LoRA) に拡張。 公式 Anima Turbo LoRA も同じ範囲を target にしている(検証で 1016 keys 確認)。
4.3 Phase B v2 — wide LoRA + R3GAN OFF で mean collapse
wide LoRA(980 keys)に拡張したら、今度は 完全に灰緑色の平面を出力。loss は
v1 より遥かに小さく(l_dmd 0.001-0.007)、訓練ログ上は最も健全に見える
失敗。LoRA strength を変えても改善せず。
原因: DMD2 単体は「real distribution の方向」を示すだけ。LoRA capacity が大きい ほど 「data distribution の mean を出力すれば DMD gradient はゼロになる」 という degenerate な解に収束しやすい。R3GAN なしでは「sharp なものを出せ」と gen に教える信号がないので、訓練が進むほど mean に潰れていく。
→ 解決: R3GAN(または同等の reward / classifier loss)を必ず投入。DMD2 系の 全公式実装(NVIDIA DMD2, Z-Image DMDR, Hyper-SD)で adv 系 loss が必須なのは このため。
4.4 Phase B v3a — gamma=0.1 で D が即爆発
grid search の 100-200 step では gamma=0.1 が安定に見えていた:
[step 60/100] d_r1=0.020 d_r2=0.015 l_disc=0.017 ← 健全
しかし本番(2000 step)で開始 30 step 以内に爆発:
[step 10/2000] d_r1=67.5 d_r2=74.8 l_disc=7.1 ← 既に異常
[step 30/2000] d_r1=1648.0 d_r2=1821.6 ← guard 発火 abort
原因推測:
- 短時間 grid search は ランダム初期化の運で偶然安定 zone に居ただけ
- 本番の異なる初期化 + 長時間 → 不安定境界を越えた
- gamma=0.1 は Anima latent では 安定境界の崖際
4.5 Phase B v3b — gamma=1.0 で長期 mean collapse + 最終 D 爆発
gamma=1.0 で training は確かに 1500 step まで全 metric 健全:
[step 1000/2000] l_dmd=0.001 l_consist=0.005 d_r1=0.005 l_disc=0.004 ← 全部小さい
しかし step 500/1000/1500 の中間 ckpt で生成テストすると全部 mean collapse:
- step 500: 白い平面
- step 1000: 白い平面
- step 1500: 青+白の blob
しかも step 1380 から D が「目覚め」始め、step ~1600 で d_r1=2656 で abort:
[step 1380/2000] d_adv=3.73 d_r1=0.36 d_r2=0.22 ← D が動き始める
[step 1510/2000] d_adv=0.00 d_r1=0.67 d_r2=0.45 ← じわじわ拡大
[step ~1600] d_r1=2656.0 d_r2=3043.2 ← abort
核心の理解:
- gamma=1.0 は D が 静か → 突然動く → 爆発 のパターン
- 静かな間(d_r1 ~ 0.005)は D が adv 信号を gen に渡せず、gen は mean に collapse
- D が動き始めた頃には gen は既に degenerate state
- ckpt が「健全に見える」のは loss だけ。実態は破綻
これが 「R3GAN の安定 zone が存在しない」 という最終診断の根拠。
4.6 失敗パターンの直交性
| Phase A | B v1 | B v2 | B v3a | B v3b | |
|---|---|---|---|---|---|
| failure mode | gradient damage(ノイズ) | degenerate(緑) | mean collapse | D 爆発 abort | D 静止 → mean collapse → D 爆発 |
| 根本原因 | R3GAN γ 過大 | LoRA target 狭 | adv なし | γ 小すぎて D 暴走 | γ 大すぎて D が adv 信号出さず |
| 検出 | step 1000+ d_r1 | 生成テスト即 | 生成テスト即 | step 30 で guard | 中間 ckpt 生成テスト |
| 対策 | γ grid search + guard | wide LoRA | R3GAN を入れる | γ 上げる | γ 下げる(でも v3a に戻る) |
5 つの failure mode は互いに直交かつ循環(γ 下げると v3a、上げると v3b)。 Anima latent で R3GAN を安定させる γ は、存在するとしても極めて狭く、 我々の grid 解像度では発見できなかった。
4.7 周辺で踏んだ Modal / diffusion-pipe / ComfyUI 罠
蒸留の本体とは別に、インフラ側で踏んだバグ:
diffusion-pipe を programmatic に使う際の 8 件
| 罠 | 症状 | 対処 |
|---|---|---|
models/, utils/ が namespace package(__init__.py なし) |
site-packages 側の utils に shadow されて from utils.common import 失敗 |
importlib.util.spec_from_file_location で強制ロード(scripts/distill/anima_loader.py) |
CosmosPredict2Pipeline(cfg) の dtype が torch.dtype 必須 |
tensor() argument 'dtype' must be torch.dtype, not str |
cfg["model"]["dtype"] = torch.bfloat16(文字列禁止) |
load_text_encoder() / load_vae() メソッドが 存在しない |
AttributeError | load_diffusion_model() だけ呼ぶ、残りは __init__ で完了 |
MiniTrainDIT.forward は padding_mask 必須(None 不可) |
transforms.functional.resize(None, ...) TypeError |
torch.zeros(B, 1, H, W) を渡す |
| VAE input が bfloat16 必須 | Input type (float) and bias type (BFloat16) should be the same |
vae_encode 内で auto-cast |
DiT 入力 (noisy, t, cond) の dtype 統一必須 |
expected mat1 and mat2 same dtype |
dit_forward helper で全部 weight dtype に揃える |
torchvision import するが requirements に無い |
ModuleNotFoundError |
image に明示インストール |
| save の filter で integer buffer を落とすと壊れる | ロード後ノイズ | float 限定 filter は廃止、全 tensor 保存 |
ComfyUI LoRA 形式
Anima/Cosmos 用 LoRA は lora_A.weight / lora_B.weight(NOT lora_down/up)、
diffusion_model. prefix 必須。PEFT 出力からの変換は modal_app.py::_convert_peft_to_comfy_lora。
SDXL 流 lora_down/up に変換すると ComfyUI が key 認識できずランダム scaling で
適用 → 出力が緑化(これも Phase B v1 のもう 1 つの寄与因子だった可能性)。
Modal 運用
| 罠 | 対処 |
|---|---|
modal run --detach の local CLI が早く戻る |
完了確認は modal app list / modal app logs <id> |
print() の block buffering で logs 滞留 |
PYTHONUNBUFFERED=1 を env に追加 |
| Volume commit は subprocess 終了時のみ | 訓練ループ内で modal.Volume.from_name(...).commit() を定期発行 |
modal volume cp は cross-volume 不可 |
両 volume mount した Modal function で shutil.copy |
run_in_background=true + TaskStop で app が "detached_disconnected" に残る |
必ず --detach を一緒に付ける(明示 detach) |
Anima ckpt は net. prefix 前提で ComfyUI が arch 検出 |
保存時に {"net." + k: v for k, v in sd.items()} |
4.8 コスト・時間の実測値
| タスク | 時間 | コスト |
|---|---|---|
| dataset 生成(B200 × 10 並列) | 40 分 | $44 |
| Path A baseline 確認(Turbo LoRA DL + 10 枚生成) | 5 分 | ~$1 |
| Phase A: full DiT 訓練(失敗) | 11.6 h | ~$70(全損) |
| Phase B v1: Q,V LoRA(失敗) | 1.6 h | ~$10 |
| Phase B v2: wide LoRA, R3GAN OFF(失敗) | 1.6 h | ~$10 |
| Phase B v3a: wide LoRA, γ=0.1(早期 abort) | ~5 分 | ~$5 |
| Phase B v3b: wide LoRA, γ=1.0(失敗) | 4 h | ~$20 |
| R3GAN gamma grid search | 30 分 | ~$3 |
| 比較生成 30 枚 + その他 | ~$2 | |
| Modal volume(50 GB × 月) | 常時 | ~$7.5/月 |
| 累計 | ~$165 ≈ 25,000円 |
R3GAN ON で 1 step 約 +20-30%(D forward + R1/R2 backward 追加分)。
5. 続き
§4 の 5 回失敗を受け、「自前で書き下す」を諦めて 既存の動く実装を最小改造で 移植した試行が 2026-05 から始まる。各手法 (Z-Image traj / LADD / Reflow / DMD2 / SiD2 / Shortcut / PCM / DRaFT+) の移植ログ・コスト・結果は migration_log.md を参照。