松田研究室
Gap-closing plan v2作成 2026-05-23
Source: docs/findings/brush-vs-splat-37dB-gap-analysis.md + docs/findings/m4-brush-bench.md
← Document Index
Strategic plan · 4 alternatives · target 37 dB

brush PSNR gap を埋める
4 つの plan

Lego 30k で brush 37.40 dB に対し自作 24.84 dB の -12.56 dB gap を、本気で brush level (37 dB) に持ち上げる戦略 4 案を並列比較。audit (brush-vs-splat-37dB-gap-analysis.md) で「MCMC は path ではない、classic recipe parity が path」と判明、それを反映した版。

00a

Audit から得た key findings (path 設計に直結)

brush vs splat-rs 37 dB analysis

docs/findings/brush-vs-splat-37dB-gap-analysis.md の audit で 当初仮説が 2 点反転 した。それを反映した plan が以下。

  • ★ brush は MCMC 非搭載でも 37 dB
    brush-train/src/config.rs: λ_Σ / λ_o / Eq.9 relocation すべて無し、SGLD noise weight も default は 0。「MCMC で gap を埋める」path は 逆向き。brush は classic refine + 質の高い recipe のみで 37 dB を達成している
    路線転換: 37 dB の path は classic recipe parity であり MCMC ではない
  • ★ eval convention 差で apparent gap が膨らんでいる可能性
    c32-orig3dgs-bench.md §6: 同一 PLY を codebase-style (render×alpha vs gt) と paper-style (render vs gt+(1-α)·white) で測ると 28.4 dB vs 14.6 dB。brush 37.40 と splat 24.84 が同 convention で測られているか未検証
    実装ギャップ純粋差は -6〜-10 dB に下方修正される可能性、最初に eval を揃える
  • ★ grad_threshold が 1e4× 違う
    brush: 2.5e-3、splat: 2e-7。gradient signal の scale 定義 (per-pixel mean / L2 norm / sum 等) が違う可能性、直接比較不能
    refine recipe を「写経」するには grad signal 計算を揃えるところから始まる
  • ★ lr_mean が 違う (brush の方が低い)
    brush: 2e-5 (init) → 2e-7 (final、exponential decay)、splat: 1.6e-4 constant。3DGS Kerbl 2023 default は 1.6e-4 だが、brush は意図的に低く取り stability 優先
    早期 iter で aggressive learning → NaN 発散 → refine 不安定の悪循環の根
  • opacity reset の方式が違う
    brush: opac_decay 0.004/step (連続 exponential decay)、splat: periodic reset (default OFF)。連続 decay は smooth な regularization として効く
    splat の opacity_reset_every=0 が「正則化欠落」として効いている可能性
  • alpha mask loss が brush のみ
    brush: match_alpha_weight=0.1(1-α_pred)·α_target を加算。splat: 該当なし
    NeRF synthetic 白背景での edge fitting に効く、推定 -0.5〜-1 dB
00b

Gap の root cause (修正版、寄与順)

audit 反映、MCMC を gap 原因から除外
#原因寄与証拠修正先
1Eval convention 不一致 (white-bg composite vs alpha-mask render の規約差)-3 〜 -6 dB (計測差、実装ギャップではない可能性)c32-orig3dgs-bench.md §6: 同 PLY で 28.4 vs 14.6 dB の split ありP1.A (1 週) / P4.A (1 週)
2LR scheduler の規模 8× 差 (lr_mean 1.6e-4 vs 2e-5、scale decay の有無)-1 〜 -2 dBbrush train.rs:80-88 ExponentialLrScheduler、splat lr_schedule.rs ExpDecay (適用 component が限定的)P1.C (2 日) / P4.C (2 日)
3opacity 正則化欠落 (brush continuous decay vs splat default OFF)-0.5 〜 -1.5 dBbrush config.rs:84 opac_decay=0.004/step、splat config opacity_reset_every=0P1.D (1 日) / P4.B (1 日)
4Refine grad signal の scale 定義差 (1e4× threshold ギャップの真因)-1 〜 -2 dBbrush 0.0025、splat 2e-7。RefineState::accumulate (refine.rs:62-75) と brush v_refine 出力の差P1.E (3〜5 日、bit-exact 検証必要)
5Alpha mask loss 欠落-0.5 〜 -1 dBbrush train.rs:203、splat 該当無しP1.F (1〜2 日)
6SH degree progressive growth 未実装 (両者とも未実装、ただし 3DGS 原著は実装)-1 〜 -2 dBsplat_core::Splat3D 固定 degree、brush も同様だが brush は 37 dB 到達のため別 path で補償P1.G (2 日)
7Refine schedule (every=200 vs 100、stop_iter は同 15k)-0.5 〜 -1 dBbrush refine_every=200、splat every=100P1.E と統合
8MCMC は gap の原因ではない (brush 非搭載、splat の MCMC 実装は別軸の貢献)0 dB (gap には無関係、ただし splat 側 MCMC 実装は卒研 axis 1 の独自貢献として残る)brush config.rs に λ_Σ / λ_o / relocation すべて無しP1 では touch しない、scope 外
9Metal / kernel layer は原因ではない0 dB (むしろ brush wgpu→Metal が 2.59× 速い)m4-brush-bench: 同 M4 Max 上で brush 9m08s vs 自作 23m40s対象外、recipe 修正完遂後に kernel 最適化 phase へ
01

4 案の overview 比較

行をクリックで切替
戦略目標 PSNR工数L1 独立Risk
P137 dB full planeval convention + LR + opacity decay + grad signal + alpha loss + SH growth + refine schedule を順次揃えて 36-37 dB 到達、MCMC は drop36 〜 37 dB (brush parity)8 〜 10 週 (集中スプリント)✓ 維持Medium
P2brush fork同じ trainer recipe で wgpu vs native Metal を head-to-head、卒研 axis 2 narrative を data で復活、PSNR は brush 37 dB を流用37 dB ± 0.5 dB (brush と同等、kernel 置換による軽微変動)3 〜 4 週✗ 破棄High
P3scope 縮小実装追加せず 24.84 dB を honest reporting、貢献軸を axis 1 (MCMC native) + axis 3 (unified memory) に集中24.84 dB (現状維持)1 〜 2 週✓ 維持Low
P4quick winsP1 の Phase A+C+D だけ短期で実装、PSNR 30-33 dB 圏に持ち上げて卒論 baseline を底上げ、残差は negative finding30 〜 33 dB (brush -4〜-7 dB)3 〜 4 週✓ 維持Low
P1
Risk: Medium

案 1: brush 37 dB に到達する full parity 路線 (recipe 9 項目)

eval convention + LR + opacity decay + grad signal + alpha loss + SH growth + refine schedule を順次揃えて 36-37 dB 到達、MCMC は drop

目標 PSNR
36 〜 37 dB (brush parity)
工数
8 〜 10 週 (集中スプリント)
タスク数
30
milestone
6

前提

audit で brush は MCMC 非搭載で 37 dB と判明。37 dB への path は classic recipe の徹底 parity。MCMC は卒研 axis 1 の独自貢献として残しつつ、本路線では touch しない。eval convention の差で apparent gap が膨らんでいる可能性 (3-6 dB) もまず潰す。

研究 3 軸への影響

axis 1 (native impl)
+ 強化 (recipe parity 達成で「Apple Silicon native でも brush 同等」を data で示せる)
axis 2 (wgpu cost)
中立 → + (kernel 性能比較が recipe gap に隠されなくなる、axis 2 の clean data 取得可能)
axis 3 (unified memory)
+ (recipe 充実で host RMW 利得が顕在化、wallclock 比較が意味を持つ)

Pros

  • L1 独立を維持しつつ 37 dB 到達 (卒論の central data 完成)
  • brush との比較が clean (kernel 単独比較が初めて意味を持つ → axis 2 narrative 復活)
  • recipe 知見の集約 = 卒論 §4 evaluation 章の主軸
  • MCMC は splat 側の独自貢献として並走 (future work 化)

Cons

  • 工数大 (8-10 週、ゼミ 1 回 + α)
  • 途中で各 phase の数字が出ないと plan 維持の意欲低下
  • eval convention 確定 + grad signal 揃え までは PSNR 改善が見えない可能性
  • phase F-H の予定が押すと卒論ゼミに間に合わない

⚠ 既存判断との衝突

  • A.2 MCMC 実装 (17.4 dB plateau) を本路線では使わない判断が要る
  • research-plan.md Phase 3 (Apple 固有最適化) の優先度を後ろ倒す必要
01

A. Eval convention 統一 (まずここから)

4 項目 · 計測差 -3〜-6 dB を確定4 / 4

brush と splat-rs が同じ convention で PSNR を測っているか検証。「実装ギャップ」と「計測差」を切り分ける、本 plan の前提整備。

#項目 / 目的工数
P1.A.1brush eval 関数 (eval.rs) のソース読解 + 数式定式化render vs gt の合成式、background 処理、test split 範囲を確認1 日
P1.A.2splat-rs eval (splat-summary / trainer.rs) の数式定式化 + brush と diffpaper-std vs codebase-style のどちらか確定1 日
P1.A.3同 PLY を 2 convention で測る reproducer scriptbrush 出力 PLY を両 eval で測り、convention 差の数値化2 日
P1.A.4splat-rs の eval を brush 準拠に統一 (config flag 化)既存 eval は backward compat で残しつつ新 default を brush 準拠に1 日
02

B. Brush 互換 config の起草

3 項目 · brush 値を一括移植3 / 3

audit で確定した brush の全 hyperparameter を「brush-compat-30k.toml」として起草、これを baseline に sweep していく。

#項目 / 目的工数
P1.B.1brush TrainConfig の全 field を splat config schema に写経lr / refine / loss / decay / sh / scheduler すべて、splat config に欠ける field は追加2 日
P1.B.2splat-train-v1 の config 拡張 (足りない field を config.rs に追加)opac_decay、alpha_mask_weight、sh_degree_init/max、lr_scale_decay 等。validation も拡張2 日
P1.B.3smoke 5k iter で eval convention 後の baseline 数字を確定A 完了後の「真の現状」を測定、ここから phase 毎の Δ を取る1 日
03

C. LR scheduler を brush に揃える

4 項目 · -1〜-2 dB 推定0 / 0

lr_mean を 1.6e-4 → 2e-5 (init) + exponential decay、lr_scale にも decay 追加。早期 iter の stability を取り戻す。

#項目 / 目的工数
P1.C.1lr_mean init = 2e-5、final = 2e-7、exp_decay 全 iter で適用brush 値そのまま、kerbl 2023 vs brush の差を smoke で確認1 日
P1.C.2lr_scale exp_decay 追加 (init 7e-3 → final 5e-3)現状 splat は constant、brush は decay。Adam の m/v invariance も要確認1 日
P1.C.3per-component LR の比率を brush に揃える (opacity 4× 低、rotation/sh 2× 高)現状 splat は opacity 高、brush は低。Adam scale invariance test と整合1 日
P1.C.4C.1-3 後の Lego 30k smoke で Δ 計測 (~+1〜2 dB 期待)phase C 単独効果を確認、効かない場合は早期に逃げ道検討1 日 (run)
04

D. Opacity decay の連続化

3 項目 · -0.5〜-1.5 dB 推定3 / 3

splat 現状の opacity_reset_every (周期 reset) を、brush の opac_decay (per-step exponential) に置き換える。

#項目 / 目的工数
P1.D.1Per-step opacity decay の実装 (Adam step 後に raw_opacity *= (1 - 0.004))apply_mcmc_opacity_l1 と同じ pattern で host RMW、新関数 apply_opacity_decay1 日
P1.D.2decay rate の sweep (0.001 / 0.004 / 0.01)5k smoke で 3 点、最適値を 30k 候補に1 日
P1.D.3C+D 後の Lego 30k smoke で累積 Δ 計測A+B+C+D で初の「visible improvement」想定 (3 〜 5 dB)1 日 (run)
05

E. Refine grad signal の bit-exact 揃え

5 項目 · -1〜-2 dB 推定 + 後段の前提0 / 0

grad_threshold が 1e4× 違う真因 = grad signal の scale 定義。brush の v_refine 出力と splat の RefineState::accumulate を bit-close まで揃える。

#項目 / 目的工数
P1.E.1brush rasterize_backwards.wgslv_refine 出力数式を抽出brush-arch.md §5.1 の "v_refine: MCMC-like growth signal" 部の式を文章化1 日
P1.E.2splat RefineState::accumulate (refine.rs:62-75) の式と比較同 (cam, view, splat) で iter 1 の v_xy が brush v_refine と bit-close か検証2 日
P1.E.3差分があれば splat 側を brush 準拠に書き換えL2 norm vs raw vs sum 等の差、test fixture で固定2 日
P1.E.4refine.every を 100 → 200 (brush 値) に揃え + grad_threshold 再 calibrate新 signal scale で grad_threshold を bisect (1e-3 / 5e-3 / 1e-2)2 日
P1.E.5A+B+C+D+E 後の Lego 30k full run中間 gate: splat count > 200k かつ PSNR > 30 dB 期待1 日 (run)
06

F. Alpha mask loss + auxiliary regularization

3 項目 · -0.5〜-1 dB 推定2 / 2
#項目 / 目的工数
P1.F.1Alpha mask loss kernel + host implementationloss.metalcompute_alpha_match を追加、weight 0.1 で combine2 日
P1.F.2BG color (white / black / random) の selectable 化brush は config で BG 切替、splat も同等に1 日
P1.F.3A+B+C+D+E+F 後の Lego 30k smokephase F 単独効果 ~0.5-1 dB 確認半日 (run)
07

G. SH degree progressive growth

3 項目 · -1〜-2 dB 推定3 / 3
#項目 / 目的工数
P1.G.1SH degree を 0 → max を 1000 iter 毎に unlock する schedulertrain_loop.rs に degree mask、project.metal 側で sh_degree を per-iter uniform 化2 日
P1.G.2SH coeff の高 band は unlock まで 0 固定 (gradient も 0 mask)Adam state も該当 band は 0 freeze1 日
P1.G.3G 後の Lego 30k smokephase G 単独効果 ~1 dB 確認半日 (run)
08

H. 最終 bench + multi-scene + 卒論差替え

5 項目 · 数字を確定して卒論へ2 / 4
#項目 / 目的工数
P1.H.1Lego 30k × 4 sample variance test (新 baseline)mean ± std で band 確定、systematic vs sample variance 区別2 日 (並列 run)
P1.H.2multi-scene (chair / ficus / drums / hotdog / mic / materials / ship) で 30kA.4 と同じ手順、scene mean ± std を新 recipe で3 日 (並列 run)
P1.H.3brush との per-component breakdown 表各 phase A-G が brush parity にどれだけ近づけたかの寄与表1 日
P1.H.4卒論 §4 evaluation 章 + A.5 final ablation 表を全面 updatecentral table を「brush 同等の数字」で書き換え2 日
P1.H.5§5.4 negative findings を「recipe gap → parity 達成」narrative に再構成「scale_reg 3 連敗 + MCMC 4 連敗 → recipe parity で帰結」のストーリー1 日
M

Milestone gates

6 個 · 各 gate で継続 / abort 判定
#label / gateabort if
P1.M1eval convention 確定 (Week 1 末) — 2026-05-24 closurebrush と splat の eval 数式が同一 or 差分が dB で定量化 — symmetry test で完全対称崩壊実証 (両 trainer 反対 convention で 1-2 dB)、coupling 構造発見、apparent gap 仮説 falsifiedeval を統一できない → P3 (negative finding 化) に rollover、measurement story として書く
P1.M2LR + opacity decay 効果確認 (Week 3 末)5k smoke で PSNR > 22 dB (現状 ~16-18 dB 圏から +4 dB)Δ < 2 dB → recipe 移植の前提 (config 等価性) を再点検、+1 週 buffer
P1.M3grad signal 揃え後 30k full (Week 4 末) — 2026-05-24 passLego 30k で PSNR > 30 dB (brush convention 明記) + splat count > 200k — **実測 35.237 dB (+5.24) / 846,689 splats (+646k)**PSNR < 28 dB → grad signal 解析が間違いの可能性、Phase E を rework or P2 (fork) 検討
P1.M4F+G 後の smoke (Week 6 末) — 2026-05-24 pass-by-defaultPSNR > 34 dB + alpha loss + SH growth が安定 — **35.237 dB で M3 と同時 pass**PSNR plateau → P4 (現状で確定 + future work narrative) に縮退
P1.M5Final (Week 8 末) — 2026-05-25 完全達成 + brush 超えLego PSNR > 36 dB (brush -1 dB 圏内) + multi-scene mean > 32 dB — **Lego val 36.106 dB ✅** + **8 scene mean 33.49 dB ✅** (brush mean 32.86 を **+0.63 dB 上回り**)、Phase D re-chain 全 8 scene 完遂 ✅gap 残る → 卒論で「97% parity 達成 + 残差 X dB の attribution」として honest reporting
P1.M6Phase G axis 1 optimization — 2026-05-26 完遂 + Pareto extensionaxis 1 最適化 4 candidate (G.1 early stop / G.2 brush audit / G.3 SH progressive / G.4 multi-cam dropped) で Pareto landscape 確定 + universal quality improvement 発見(該当なし、Phase G は M5 後の future work 拡張)
W

Week 別 実行順序

8 週想定
Week 1
~5/30
A: eval convention 統一
  • P1.A.1〜4 eval 数式 + reproducer + 統一
  • 計測差を確定 (apparent gap の何 dB が convention か)
Week 2
~6/6
B+C: config 移植 + LR 揃え
  • P1.B.1〜3 brush-compat-30k.toml 起草
  • P1.C.1〜4 LR scheduler 揃え + smoke
Week 3
~6/13
D+E 前半: opacity decay + grad signal 解析
  • P1.D.1〜3 opacity decay 実装 + smoke
  • P1.E.1〜2 brush v_refine 解析
Week 4
~6/20
E 完遂: grad signal bit-exact
  • P1.E.3〜5 splat 側 grad signal 修正 + 30k full
  • 中間 gate: PSNR > 30 dB + splat 200k 達成
Week 5
~6/27
F: alpha mask loss
  • P1.F.1〜3 alpha loss 実装 + BG 切替 + smoke
Week 6
~7/4
G: SH degree progressive
  • P1.G.1〜3 SH progressive 実装 + smoke
Week 7
~7/11
H 前半: Lego variance + multi-scene 着手
  • P1.H.1 Lego variance test
  • P1.H.2 multi-scene 半数 run
Week 8
~7/18
H 後半: multi-scene 完遂 + 卒論 update
  • P1.H.2 残 multi-scene
  • P1.H.3〜5 卒論章 update
Decision rule
Phase 毎に smoke gate を設置、各 gate で 継続 / abort / pivot 判定。Week 4 末の M3 (PSNR 30 dB) が 本路線の生命線、ここで通らないと 37 dB 目標は撤回。
Abort condition
M3 (Week 4 末) で 28 dB 未達なら P2 (fork) or P4 (partial + negative) に切替。Week 6 末 M4 で 34 dB 未達なら P1 を打ち切り、現状値 + future work narrative で卒論 finalize。
99

使い方

本 PlanVue は brush PSNR gap をテーマに 4 plan を持つ template。同形式の別テーマ (e.g. インクリメンタル学習化 plan、CUDA baseline 拡張 plan) は plans 配列を差し替えるだけで複製可能。各 plan は独立した sections / weeks / milestones / decisionRule / abortCondition を持つので、 monthly plan (pages/plan.vue) と違って 複数戦略の並列比較 + 採用 / 切替 / abort 管理 用途に向く。

運用: tab を切替えて plan 詳細を読む。採用 plan が決まったら sections の items の status プロパティを 'done' / 'wip' / 'skip' に変更、Week 別表示の進行管理にそのまま使える。Phase gate (M1〜M5) が想定通り動くか毎週確認、不通過なら abort condition に従って pivot。

© 2026 大竹律輝 — 松田研究室