vggt_omega 패키지 그대로 호출260630 stitch layer 탐색(job 29986, ℓ̂=2 결정, MSE 7.61e-3)에 이어, connector/stitched backbone/loss/train script 구현이 진행됐다. 코드가 여러 파일(connector, aggregator wrapper, loss, train entry)에 걸쳐 있어 전체 데이터 흐름과 파라미터 규모를 한 문서에 layer 단위로 정리할 필요가 있었다.
또한 VGGT-Ω 학습 recipe를 얼마나 "그대로" 가져왔는지 애매한 상태였다 — 어떤 부분을 원본대로 유지했고 어떤 부분을 의도적으로 단순화했는지 추적하지 않으면, 이후 성능 이슈가 생겼을 때 "우리 구현 버그"인지 "의도적 단순화의 부작용"인지 구분이 안 된다.
Input(raw batch → VAE latent) → Connector(Conv3d) → Aggregator(frame/inter-frame blocks) → Head(Camera/Dense) → Loss 순으로 전체 텐서 shape을 추적하고, VGGT-Ω 공개 코드(vggt_omega 패키지)와 우리 학습 코드(train_lgm_robocasa_vggt_v0.py)를 항목별로 대조했다.
block 0, 1은 skip하고 block 2부터 forward (stitch layer ℓ̂=2 결정에 따름). inter-frame attention은 block_idx ∈ {2,6,9,14,20}에서만 "register"(cam+register 토큰 1632개만 cross-frame, patch 74592개는 frame-local 유지 — VGGT-Ω "Omega" 트릭, 메모리 30% 절감), 나머지는 "global"(전체 96·794 토큰 cross-attend).
| 대상 | 모듈 | 개수 | Trainable params |
|---|---|---|---|
| Aggregator (frame + inter-frame) | qkv/proj/fc1/fc2, 1024-dim | 48 block × 4 = 192 Linear | ~50.4M |
| CameraHead trunk | qkv/proj/fc1/fc2, 2048-dim | 4 block × 4 = 16 Linear | ~16.8M |
| Connector | Conv3d(16→1024) | 1 | ~2M |
| 합계 trainable | ~69M | ||
frozen: VGGT-Ω 1.14B 본체 + DenseHead Conv2d 전부. r=64, alpha=32, target_modules=["qkv","proj","fc1","fc2"].
"VGGT 코드를 가져왔다"는 표현은 부정확 — 모델(Aggregator/CameraHead/DenseHead)은 vggt_omega 패키지를 수정 없이 그대로 호출하지만, 학습 루프와 loss는 부분적으로만 이식하고 나머지는 의도적으로 단순화했다. 항목별 비교:
| 항목 | VGGT base 원본 | 우리 구현 |
|---|---|---|
| Pose 표현 | 9-DoF absT_quaR_FoV | 동일 |
| Loss type | L1 (paper는 smooth-L1이나 코드 주석상 L1이 더 stable) | L1 동일 |
| Outlier clamp | loss_T.clamp(max=100) | 동일 |
| 가중치 (w_T,w_R,w_FL) | 1.0, 1.0, 0.5 | 동일 |
| Multi-stage decay | pose_enc_list iterative refinement × γ^(N-k-1), γ=0.6 | ❌ 없음 — VGGT-Ω CameraHead는 single scalar pose_enc만 출력, iter loop 자체가 구조상 불가능 |
| Valid frame mask | point_masks.sum()>100 per frame | ❌ 모두 valid 가정 |
| 항목 | VGGT base | 우리 |
|---|---|---|
| L_reg (channel-wise L2, C=1이라 L1과 동일) | ✓ | ✓ |
| Conf-weighted (γ·L_reg·conf − α·log conf) | γ=1.0, α=0.2 | 동일 |
| depth_conf = 1+exp(logit) | ✓ | ✓ |
| check_and_fix_inf_nan 래퍼 | 모든 step 적용 | nan_to_num만 (단순화) |
| filter_by_quantile (outlier drop) | valid_range>0일 때 적용 | ❌ 없음 |
| gradient_loss_multi_scale_wrapper | log-depth 공간 + per-scale weighting | 단순 4-scale avg-pool + L1 gradient만 |
| normal_loss (surface normal 비교) | 선택적 적용 | ❌ 없음 |
| mask.sum()<100 skip | ✓ | 동일 |
vggt_omega 패키지 수정 0으로 그대로 호출. LGMConnector(Conv3d), stitch skip 로직(block 0,1), LoRA는 모두 우리가 추가한 부분(원본에 없음, VGGT는 full fine-tune)이 문서화 작업으로 "VGGT-Ω 기반 LGM"이 정확히 무엇을 재사용하고 무엇을 자체 구현했는지 명확해졌다. 모델 forward path(Aggregator/Head)는 원본 그대로라 신뢰도가 높고, loss는 핵심 항목만 구현된 축소판이라는 게 확인됐다 — 즉 향후 학습이 예상보다 unstable하거나 depth quality가 기대에 못 미치면, 우선 의심할 곳은 quantile filtering 부재로 인한 outlier 민감도와 log-depth gradient 대신 raw-depth gradient 사용이다.
또한 camera loss의 multi-stage decay 부재는 우리 실수가 아니라 VGGT-Ω 공개 CameraHead 구조(single-stage) 자체의 한계임을 명확히 해뒀다 — 이 부분을 "버그"로 오인해 나중에 시간 낭비하는 것을 방지.
Depth loss 5개 미구현 항목이 학습 안정성에 실질적 영향을 주는지 미검증. w_cam/w_depth 가중치도 추정치 상태.
"더 충실하게" 맞추려면 추가할 항목(전부 추가 시 ~50줄 규모):
gradient_loss_multi_scale_wrapper를 vggt/training/loss.py에서 그대로 포팅 (log-depth gradient + per-scale weighting)filter_by_quantile 활성화 (통상 valid_range=0.98) — outlier robustnesscheck_and_fix_inf_nan을 모든 loss 텀에 적용50K step 학습 완료 후, 위 항목 추가 전/후로 depth AbsRel·camera pose error ablation 비교 예정.