[{"data":1,"prerenderedAt":261},["ShallowReactive",2],{"finding:p1-a-3-cross-eval-reproducer":3,"finding-runs:p1-a-3-cross-eval-reproducer":214,"finding-related:p1-a-3-cross-eval-reproducer":215},{"meta":4,"impact":36,"sections":42},{"id":5,"title":6,"subtitle":7,"eyebrow":8,"date":9,"status":10,"category":11,"polarity":12,"axes":13,"tags":17,"task_code":28,"related_runs":29,"related_findings":31},"p1-a-3-cross-eval-reproducer","P1.A.3 cross-eval reproducer — brush convention で 24.879 → 1.67 dB に崩壊、主仮説 falsify","P1.A.4 (eval を brush 準拠 convention で再計算する CLI flag) を実装し、splat-rs lego sh3 30k final.ply (training baseline 24.879 dB) を 4 通り (legacy\u002Fbrush × quantize on\u002Foff) で eval。結果は audit §6 の主仮説 (brush 流で +3〜+5 dB) を完全に falsify、brush convention に切り替えると PSNR は逆に -23 dB 崩壊して 1.67 dB。原因は splat-rs trainer が white-bg target 前提で学習されており、背景 pixel を白い不透明 splat で埋めるよう収束しているため、bg=ZERO premultiplied 比較では背景全体で MSE≈1 が乗る。これは bug ではなく training\u002Feval convention の coupling を実証した結果で、apparent gap 仮説 (eval pipeline だけ揃えれば +3〜+5 dB) が成立しないことを示す。M2 以降の brush parity loss は「training-loss convention も brush 化」を含む必要がある。","P1 Phase A · A.3 reproducer · M1 gate closure","2026-05-24","stable","experiment","negative",[14,15,16],1,2,3,[18,19,20,21,22,23,24,25,26,27],"p1","phase-a","milestone-m1","brush-parity","eval","convention","psnr","premultiplied","reproducer","falsified-hypothesis","P1.A.3 + P1.A.4",[30],"lego-sh3-30k (splat-rs 24.879 dB legacy\u002Fval)",[32,33,34,35],"p1-a-eval-convention-audit","p1-a-1-brush-eval-audit","p1-a-2-splat-eval-audit","brush-vs-splat-37dB-gap-analysis",{"summary":37,"rank":38,"verdict":39,"delta_wallclock":40,"delta_psnr":41},"splat-rs `final.ply` (24.879 dB legacy\u002Fval baseline) を brush 準拠 convention (premultiplied GT + bg=ZERO 比較 + 8-bit roundtrip) で再評価すると **1.67 dB に崩壊**。audit §6 が予測した +3〜+5 dB 底上げと逆方向に -23 dB。原因は trainer が white-bg target で学習されており、背景領域を opaque-white splat で埋めるよう収束した結果、brush 流の bg=ZERO 比較では背景 pixel 全体で MSE≈1 が systematic に乗る。`view_00.png` 目視確認 (背景は白い不透明領域) で機構を確定。**training と eval の convention は coupling しており、eval pipeline だけ揃える apparent-gap 仮説は不成立**。卒研 P1.M2\u002FM3 に向けては「training loss も brush 化 (RGBA 4ch L1 を α=0 領域で背景に penalty を吹かさない構造)」が必須要件。8-bit quantize 単体の impact はほぼ無視可能 (legacy 24.879 → 24.879、brush 1.605 → 1.667、+0.06 dB)。","high","hypothesis-falsified-stronger-finding","N\u002FA (eval only)","-23.21 dB (brush convention 化で 24.879 → 1.667)",[43,46,51,54,106,108,145,147,151,153,160,162,165,167,175,177,183,185,191,193,197,199,205,207],{"type":44,"text":45},"lead","\u003Cstrong>P1.A.4 (eval を brush 準拠 convention で再計算する CLI flag)\u003C\u002Fstrong> を \u003Ccode>splat eval\u003C\u002Fcode> subcommand として実装し、\u003Cstrong>P1.A.3 reproducer\u003C\u002Fstrong> として splat-rs \u003Ccode>lego-sh3-30k\u002Ffinal.ply\u003C\u002Fcode> を \u003Cstrong>4 通り (legacy\u002Fbrush × quantize on\u002Foff)\u003C\u002Fstrong> で再評価。\u003Cstrong>audit §6 の \"brush 流で +3〜+5 dB\" 主仮説は完全に falsify\u003C\u002Fstrong>、代わりに \u003Cstrong>training-eval convention が coupling している\u003C\u002Fstrong> という、より重要な構造的発見が得られた。M1 gate (eval convention 統一確定 + 数式 diff 定量化) は \u003Cstrong>実測値で完全 closure\u003C\u002Fstrong>。",{"type":47,"label":48,"variant":49,"text":50},"callout","結論 (M1 closure)","danger","\u003Cstrong>apparent gap 仮説 (eval だけ揃えれば +3〜+5 dB) は falsified\u003C\u002Fstrong>。brush convention に切り替えると \u003Cstrong>24.879 → 1.667 dB に -23 dB 崩壊\u003C\u002Fstrong>。原因は trainer が white-bg target で学習されており、背景領域を \u003Cstrong>opaque-white splat で埋めるよう収束\u003C\u002Fstrong>している (`view_00.png` で目視確認、背景は白い不透明領域)。brush 流の bg=ZERO premultiplied 比較では、この opaque-white 背景 vs premultiplied GT=(0,0,0) で \u003Cstrong>背景 pixel 全体で MSE≈1 が systematic に乗る\u003C\u002Fstrong>。\u003Cstrong>brush parity は training loss も brush 化 (α=0 領域で背景に penalty を吹かさない構造)\u003C\u002Fstrong> を必要とする。",{"type":52,"text":53},"heading","1. 4 通り eval 実測 table",{"type":55,"columns":56,"align":64,"rows":68},"table",[57,23,58,59,60,61,62,63],"#","split","quantize8","PSNR (dB)","ΔPSNR vs baseline","ΔPSNR vs brush 37.40","備考",[65,66,66,67,65,65,65,66],"right","left","center",[69,78,84,91,97,103],[70,71,72,73,74,75,76,77],"1","legacy","val","off","**24.879**","0.000 (baseline)","-12.521","sanity check pass、訓練時 result.toml と完全一致",[79,71,72,80,81,82,76,83],"2","on","24.879","+0.000","8-bit roundtrip 単体は impact 無視可能",[85,86,72,73,87,88,89,90],"3","brush","**1.605**","-23.274","-35.795","premultiplied GT vs opaque-white 背景で MSE≈1 崩壊",[92,86,72,80,93,94,95,96],"4","**1.667**","-23.212","-35.733","**完全 brush 準拠 (val)**、3 と +0.06 dB のみ差",[98,71,99,100,101,100,100,102],"5","test","—","N\u002FA","test split PNG が 36\u002F200 しか disk に無い (要再 DL、後続 task)",[104,86,99,100,101,100,100,105],"6","同上 (dataset 不完全)",{"type":52,"text":107},"2. audit §6 主仮説の falsification table",{"type":55,"columns":109,"align":115,"rows":116},[110,111,112,113,114],"軸","audit §6 予測","A.3 実測","差分","判定",[66,65,65,65,66],[117,123,128,134,139],[118,119,120,121,122],"D2 (bg composite)","+3〜+5 dB (splat 底上げ)","-23 dB (崩壊)","-28 dB","**仮説と逆方向、falsified**",[124,125,126,100,127],"D3 (α-mask premultiply)","+1〜+2 dB (splat 底上げ)","(D2 と一括)","D2 と coupling、独立評価不能",[129,130,131,132,133],"D4 (8-bit roundtrip)","-0.5〜-1 dB (splat 微減)","+0.06 dB (微増)","+~1 dB","**impact ほぼ無視可能、仮説と方向逆**",[135,136,137,100,138],"D1 (split file)","-1〜-2 dB (test 難)","(dataset 不完全)","後続 task で実測予定",[140,141,142,143,144],"**合計 (val 限定)**","**+2.5〜+4 dB 底上げ**","**-23 dB 崩壊**","**-27 dB**","**主仮説 falsified**",{"type":52,"text":146},"3. 真因: training\u002Feval convention の coupling",{"type":47,"label":148,"variant":149,"text":150},"メカニズム","warning","splat-rs trainer は \u003Cstrong>white-bg pre-composite した GT\u003C\u002Fstrong> (`load_rgba_white_bg`) を target に L1\u002FSSIM loss で fit する。background pixel (元 PNG α=0 領域) は target=(1,1,1) なので、loss が \u003Cstrong>背景にも \"白く塗れ\" と要求\u003C\u002Fstrong>する。これに対し rasterize.metal は bg-agnostic な premultiplied 出力 (`pix_out = Σ rgb·α·T`, `α_out = 1-T`) を返すため、trainer はこの要求を \u003Cstrong>opaque-white splat を背景に大量配置する\u003C\u002Fstrong> ことで満たした。\u003Cbr>\u003Cbr>\u003Cstrong>結果として final.ply は \"白い不透明背景を持つ rendered\" を返す model\u003C\u002Fstrong>。これを brush 流 (背景 = premultiplied GT = (0,0,0) と直接比較) で eval すると、背景 pixel 全体で \u003Cstrong>rendered ≈ (1,1,1) vs target = (0,0,0)、MSE ≈ 1\u003C\u002Fstrong>。NeRF Synthetic lego の背景比率は 50% 以上なので、image 全体 MSE ≈ 0.5 → PSNR = -10·log10(0.5) ≈ 3 dB 帯に押し下げ。実測 1.67 dB はこの帯 (frontier 50% で完全一致しても背景で 100% miss するので)。",{"type":52,"text":152},"4. 機構の目視確認",{"type":154,"items":155},"list",[156,157,158,159],"\u003Ccode>splat\u002Fruns\u002Flego-sh3-30k\u002Fview_00.png\u003C\u002Fcode> (forward_rgba output 直書き、白背景に lego モデル) → trainer 出力は \u003Cstrong>背景が白い不透明領域\u003C\u002Fstrong>、premultiplied 出力なら背景は透明 RGB=0 のはずだが、white-bg loss で fit された結果 \u003Cstrong>opaque-white splat が背景を埋めている\u003C\u002Fstrong>","\u003Ccode>gt_00.png\u003C\u002Fcode> (load_rgba_white_bg で white-bg composite 済み target) → 同じ白背景、これが loss target、両者は legacy convention 下で 30.36 dB と密接にマッチ","brush convention の per-view PSNR を見ると \u003Cstrong>全 view で 1.6 dB 帯に systematic に集中\u003C\u002Fstrong> (max 2.84, min -0.62, median 1.65) → noise でなく structural mismatch、原因が \"前景 fit\" でなく \"背景 mismatch\" であることを示唆","rendered の clamp 範囲 (`min \u003C -0.6` view あり) → premultiplied 期待では rendered ∈ [0, α] のはずが overshoot あり、bg-as-opaque-white の training pressure で SH coefficient が saturate していることを示唆",{"type":52,"text":161},"5. brush convention で test split が測れなかった件",{"type":163,"text":164},"paragraph","\u003Ccode>\u002FUsers\u002Fotkrickey\u002Fdev\u002F3dgs-workspace\u002Fdatasets\u002Fnerf_synthetic\u002Flego\u002Ftest\u002F\u003C\u002Fcode> には \u003Ccode>r_*.png\u003C\u002Fcode> が 36 frame しか無く、transforms_test.json は 200 frame を参照 (差分は normal\u002Fdepth aux PNG)。**dataset の RGB test split が不完全**。後続 task (P1.A.3 followup or P1.B) で \u003Ccode>nerf_synthetic.zip\u003C\u002Fcode> の test 部分を再 DL するか、別 dataset (m4-brush-bench に存在する場合) を使う必要あり。今回 val (100 view) で M1 gate を締めるのに impact 無し (主仮説 falsify には val 1 set で十分)。",{"type":52,"text":166},"6. P1.A.4 実装内容 (本 task で実装した部分)",{"type":154,"ordered":168,"items":169},true,[170,171,172,173,174],"\u003Ccode>splat\u002Fcrates\u002Fsplat-io\u002Fsrc\u002Fdataset.rs\u003C\u002Fcode> — \u003Ccode>GtConvention { WhiteBg, Premultiplied }\u003C\u002Fcode> enum + \u003Ccode>load_nerf_synthetic_with_convention(dir, split, convention)\u003C\u002Fcode> wrapper + \u003Ccode>load_rgba_premultiplied\u003C\u002Fcode> 関数 (byte 空間 premultiply、brush \u003Ccode>scene.rs:212-232\u003C\u002Fcode> AlphaMode::Transparent と同等)","\u003Ccode>splat\u002Fcrates\u002Fsplat-cli\u002Fsrc\u002Fcmd\u002Feval.rs\u003C\u002Fcode> (新規) — \u003Ccode>splat eval --ply --dataset --split --convention --quantize-8bit\u003C\u002Fcode> subcommand、既存 trained PLY を再評価。training は触らない (config 拡張も避け、CLI flag 経路で完結)","\u003Ccode>splat\u002Fcrates\u002Fsplat-cli\u002Fsrc\u002Fmain.rs\u003C\u002Fcode>, \u003Ccode>cmd\u002Fmod.rs\u003C\u002Fcode> — subcommand wire","既存 \u003Ccode>compute_psnr\u003C\u002Fcode> (train.rs:182) は \u003Cstrong>未変更\u003C\u002Fstrong>、新 \u003Ccode>compute_psnr_legacy\u003C\u002Fcode> + \u003Ccode>compute_psnr_brush\u003C\u002Fcode> を eval.rs に複製 (training 内部の loss path への影響ゼロを保証)","\u003Ccode>FullConfig\u003C\u002Fcode> schema 変更なし、既存 configs\u002F*.toml は無変更で動作 (deny_unknown_fields も触らない)",{"type":52,"text":176},"7. apparent gap 仮説 falsify の意味 (audit doc §6 update 材料)",{"type":154,"items":178},[179,180,181,182],"audit §6 table の \"推定 dB shift\" 列は \u003Cstrong>実測 column を追加して update\u003C\u002Fstrong> すべき (D2: -23 dB \u002F D4: +0.06 dB \u002F 合計: -23 dB)","audit §6 footer の \"主仮説: -3〜-6 dB apparent gap が消える\" は \u003Cstrong>取り消し\u003C\u002Fstrong>、新仮説: \"brush parity には training loss convention も brush 化が必要、eval だけでは不可能\"","audit §11 (Phase A の残作業) の P1.A.4 は \u003Cstrong>本 task で完了\u003C\u002Fstrong>、ただし \"brush 準拠 eval が default で意味を持つ\" には trainer の brush 化が前提なので、しばらく \u003Cstrong>config flag (CLI flag) として保持し default=legacy\u003C\u002Fstrong> 維持が妥当","audit §12 (卒論への含意) は補強される: \"eval convention の選択は trainer 設計と coupling する\" を \u003Cstrong>D.3 negative-findings-chapter の中核トピック\u003C\u002Fstrong> として書ける材料が揃った",{"type":52,"text":184},"8. 次 phase への申し送り (P1.B 互換 config 起草へ)",{"type":154,"ordered":168,"items":186},[187,188,189,190],"\u003Cstrong>P1.B trainer 改修\u003C\u002Fstrong>: train loop の loss を brush 流 (RGBA 4ch、target は premultiplied GT、α channel に match_alpha=0.1 weight) に切り替える設計を起草。\u003Ccode>load_rgba_white_bg\u003C\u002Fcode> → \u003Ccode>load_rgba_premultiplied\u003C\u002Fcode> を train 経路でも選択可能化、loss kernel (`splat\u002Fshaders\u002Floss\u002Floss.metal`) が premultiplied 4ch を受け取れることを確認 (既存 4ch path を活用)","\u003Cstrong>P1.A.3 followup (任意)\u003C\u002Fstrong>: NeRF Synthetic test split (200 view) を再 DL し、legacy\u002Fval baseline と test\u002Fval 差を独立に測る。これで D1 (split) の独立 impact が確定し、audit §6 row が完全更新できる","\u003Cstrong>P1.M1 gate update\u003C\u002Fstrong>: 本 finding で gate closure。audit §6 table を実測値で update、status を \"audit-complete\" → \"audit-complete-hypothesis-revised\" に変更","\u003Cstrong>plan-gap.vue\u003C\u002Fstrong>: P1.A.3 \u002F P1.A.4 → done mark、主仮説 falsify を明記、M2 (brush loss 化) を新 critical path として上位に",{"type":52,"text":192},"9. 再現手順 (artifacts なし、source \u002F dataset から完全再現可能)",{"type":194,"lang":195,"text":196},"code","bash","# build\ncd splat\ncargo build --release -p splat-cli\n\n# 4 通り sweep (test 2 通りは dataset 不完全のため skip)\nPLY=runs\u002Flego-sh3-30k\u002Ffinal.ply\nDS=\u002FUsers\u002Fotkrickey\u002Fdev\u002F3dgs-workspace\u002Fdatasets\u002Fnerf_synthetic\u002Flego\n\n# 1: legacy\u002Fval\u002Fno-quant (sanity check vs result.toml の 24.879)\n.\u002Ftarget\u002Frelease\u002Fsplat eval --ply $PLY --dataset $DS --split val --convention legacy\n# → 24.8787\n\n# 2: legacy\u002Fval\u002Fquant (8-bit impact 単体)\n.\u002Ftarget\u002Frelease\u002Fsplat eval --ply $PLY --dataset $DS --split val --convention legacy --quantize-8bit\n# → 24.8787\n\n# 3: brush\u002Fval\u002Fno-quant (premultiplied 単体 impact)\n.\u002Ftarget\u002Frelease\u002Fsplat eval --ply $PLY --dataset $DS --split val --convention brush\n# → 1.6049\n\n# 4: brush\u002Fval\u002Fquant (完全 brush 準拠)\n.\u002Ftarget\u002Frelease\u002Fsplat eval --ply $PLY --dataset $DS --split val --convention brush --quantize-8bit\n# → 1.6665\n",{"type":52,"text":198},"10. 不明点 \u002F 未確認事項 (main agent 判断用)",{"type":154,"items":200},[201,202,203,204],"\u003Cstrong>brush trainer 37.40 dB は brush convention で測られているはず\u003C\u002Fstrong> だが、brush 側で legacy convention に揃えたとき何 dB 出るか未確認 (brush trainer の training-eval は両方 premultiplied なので、convention 切り替え可能か仕組み確認要)","\u003Cstrong>test split RGB PNG 完全版の再 DL\u003C\u002Fstrong> (NeRF Synthetic 公式) — 1.x GB 程度、後続 task or P1.B 着手時に必要","\u003Cstrong>rendered overshoot (min PSNR view で -0.6 dB)\u003C\u002Fstrong> は SH の saturate を示唆、debug すれば trainer の \"opaque-white 背景埋め\" 戦略の構造詳細が見える (本 task は scope 外)","\u003Cstrong>brush mean PSNR 1.667 dB の理論値\u003C\u002Fstrong>: 背景 50% 完全 mismatch + 前景 30 dB なら image MSE = 0.5·1.0 + 0.5·0.001 ≈ 0.5005 → PSNR ≈ 3.01 dB のはずだが実測 1.67 dB と差 1.3 dB。前景の SH saturate (overshoot で MSE > 0.001) と背景比率が 50% でなく ~60-70% である可能性。\u003Cstrong>impact 小なので scope 外\u003C\u002Fstrong>",{"type":52,"text":206},"関連",{"type":154,"items":208},[209,210,211,212,213],"P1.A audit master finding: \u003Ccode>p1-a-eval-convention-audit\u003C\u002Fcode> (本 doc が §6 main hypothesis を falsify)","P1.A.1 brush eval audit: \u003Ccode>p1-a-1-brush-eval-audit\u003C\u002Fcode>","P1.A.2 splat-rs eval audit: \u003Ccode>p1-a-2-splat-eval-audit\u003C\u002Fcode>","brush vs splat 37 dB gap analysis: \u003Ccode>brush-vs-splat-37dB-gap-analysis\u003C\u002Fcode>","P1.M3 生命線 (Lego 30k で PSNR > 30 dB): legacy convention 下で 24.879 dB → +5.1 dB 不足、brush convention では遥かに遠い",[],[216,234,249],{"id":33,"title":217,"date":9,"status":10,"polarity":218,"category":219,"axes":220,"tags":221,"task_code":225,"related_runs":226,"delta_psnr":229,"delta_wallclock":230,"rank":38,"verdict":231,"impact_summary":232,"detail_path":233},"P1.A.1 brush eval audit — 数式定式化 + diff 観点 12 項目","neutral","audit",[14,15],[18,222,86,219,24,223,22,224,25,23],"a-1","ssim","alpha","P1.A.1",[227,228],"brush-lego-sh3-30k (37.40 dB report)","splat-rs-lego-sh3-30k (24.879 dB)","N\u002FA (apparent gap mechanism の特定が主目的)","N\u002FA (audit task)","audit-complete","brush eval は (1) AlphaMode::Transparent で GT を α premultiply、(2) bg=Vec3::ZERO の黒背景に render、(3) composite_bg=None で premultiplied 同士を直接比較、(4) 8-bit roundtrip 後に MSE = mean((pred−gt)²) over H·W·3、(5) PSNR = 10·log10(1\u002FMSE)。これは NeRF Synthetic (RGBA で α=0 の透明領域が支配的) において **透明領域は pred=gt=0 で完全一致** となり、MSE 分母に 0 寄与が大量に入る → conventional 「白背景に composite してから PSNR」より高く出る。splat-rs 側の eval 規約を A.2 で確認し、A.3 で「同 convention 下での真の gap」を測定する必要あり。","\u002Ffindings\u002Fp1-a-1-brush-eval-audit\u002F",{"id":34,"title":235,"date":9,"status":10,"polarity":218,"category":219,"axes":236,"tags":237,"task_code":242,"related_runs":243,"delta_psnr":245,"delta_wallclock":246,"rank":38,"verdict":218,"impact_summary":247,"detail_path":248},"P1.A.2 splat-rs eval audit — val split 100view・α 除外・rendered 黒背景の RGB-only PSNR",[14,16],[238,21,22,239,240,219,241],"phase-1","psnr-formula","convention-diff","self-trainer","P1.A.2",[244],"lego-sh3-30k","N\u002FA (本タスクでは PSNR を変えない、audit 結果のみ提示)","N\u002FA (audit のみ)","splat-rs trainer の eval は (1) val split 100 view・brush は test split 200 view、(2) PSNR は RGB のみ・α 除外、(3) rendered は raw f32 (clamp \u002F quantize なし)・brush 標準は u8 quant 後、(4) rendered は bg 合成なしで Σαi·Ti·ci のみ・target は white-bg pre-composite — の 4 つの diff 軸を持つ。training loss は 4ch (α 含む) で動くため、α 通り collapse が暗黙の white-bg 効果を作るが、convergence は不完全。P1.A.3 で 7 項目の切り分け reproducer を作り apparent gap (推定 −3〜−6 dB) を分離する。","\u002Ffindings\u002Fp1-a-2-splat-eval-audit\u002F",{"id":32,"title":250,"date":9,"status":10,"polarity":218,"category":219,"axes":251,"tags":252,"task_code":254,"related_runs":255,"delta_psnr":257,"delta_wallclock":230,"rank":38,"verdict":258,"impact_summary":259,"detail_path":260},"P1.A eval convention audit (統合) — 7 軸の diff 確定、apparent gap 推定 -3〜-6 dB",[14,15,16],[18,19,20,21,22,23,24,25,224,58,219,253],"synthesis","P1.A (M1)",[256,227],"lego-sh3-30k (splat-rs 24.879 dB)","推定 -3〜-6 dB (apparent gap 縮小、A.3 で実測予定)","audit-complete-gate-passed","両 trainer の eval pipeline を file:line で完全 audit、PSNR formula 本体 (MAX=1 \u002F log10 \u002F RGB only \u002F per-view mean) は同等だが、(1) test split (200 view) vs val split (100 view)、(2) background composite convention の **完全逆方向**、(3) 8-bit roundtrip 有無、(4) α-mask 経路、(5) clamp\u002Fquantize 等 7 軸で diff を確認。最大の発見は brush の premultiplied-α + bg=ZERO eval が NeRF Synthetic の透明領域で構造的に PSNR を +3 dB 以上嵩上げする一方、splat-rs は target に white pre-composite \u002F rendered に bg 合成なしの mismatch で convergence 残差が MSE に直接残る。apparent gap の推定 -3〜-6 dB を A.3 reproducer で実証予定、残り -6〜-9 dB が真の algorithmic gap。","\u002Ffindings\u002Fp1-a-eval-convention-audit\u002F",1782449788630]