Index
2026-08-08 — Experiment

World Forcing: VGGT-Ω REPA로 X-WAM의 1.64B depth branch를 대체할 수 있는가

X-WAM | RoboCasa 24 task × 50 rollout | arm A / B / C 3-arm 통제 실험

TL;DR

64.67%
arm C SR
+3.58
vs arm A (%p)
z=1.82
미확립
29M
vs 1.64B
0.89
최종 cos 정렬

1 배경 / 목적

질문은 “world model의 3D 일관성은 control을 사는가”다. 선행 연구 지형이 두 진영으로 갈려 있고 다리가 없다.

진영대표 연구보고 지표빠진 것
3D 일관성PAIWorld, Geometry Forcing, GEM-4D3D 지표만SR 보고 0편
표현 정렬AGRA, MECo-WAM, Spatial ForcingSR만3D 정확도 0편
X-WAM이 이 질문에 답할 수 있는 이유: depth branch가 1.64B(트렁크 4.91B의 +33%)로 분리 가능하고, policy_server.py:206run_depth=False정책 추론 시 아예 실행되지 않는다. 즉 이미 training-time-only 정규화 장치다 → 그 1.64B를 학습 시점 표현 정렬로 대체할 수 있는가?
제약 (설계의 출발점): 모델은 추론 시 카메라 파라미터도 VGGT feature도 받지 않는다 — 생성하는 프레임의 카메라를 알 수 없기 때문이고, 이것이 REPA를 택한 이유 자체다. teacher는 학습 시점에만 존재한다.

2 작업 내용

세 arm은 기하 지도신호 하나만 다르다. 레시피는 완전히 동일하다.

arm기하 지도신호추가 파라미터추론 비용최종 video_loss
A없음000.1316
Bexplicit 4D 생성 (depth branch)1.64 B0 (실행 안 됨)0.1221
Cimplicit 정렬 (VGGT-Ω REPA)0.029 B0 (teacher 학습 전용)0.1314
teacher : VGGT-Ω-1B-256 aggregator만 (camera/depth/alignment head OFF), frozen, bf16 입력 : latent 0·1·2 × 3뷰 = 9장을 한 세트로 1회 (repa_frames=all) 대응 : teacher patch 16×20 --avg_pool2d(2)--> 8×10 = student grid (정확히 2×, 보간 없음) student : blocks[19] 출력 video 토큰 720개 (= depth branch fork 지점 → arm B와 통제 비교 성립) loss : L_FM + 0.5·L_ang + 0.05·L_scale (Geometry Forcing 2항) L_ang = −mean cos( f_φ(h), y ) L_scale = mean || g_ψ(h/||h||) − y ||² 학습 : torchrun 8 GPU, bs4×accum4 = eff batch 128, lr 3e-5, 20,000 step

repa_frames는 버리는 노브가 아니라 실험의 축이다

정렬 대상 프레임을 고르는 이 노브가 선행 두 연구가 갈리는 지점 그 자체다: cond(latent 0 = 현재 관측) = Spatial Forcing(VLA), gen(latent 1·2 = 생성 프레임) = Geometry Forcing(video), all = 둘의 합. 이번 arm C는 all이다.

초안에서는 “latent 0은 clean 조건이라 정렬을 거저 만족시킨다”며 제외했으나 거저가 아니다 — DiT feature → VGGT feature 매핑은 clean 입력에서도 배워야 하고 단지 쉬울 뿐이다. 반대로 추론 시 frame 0은 정책이 실제로 조건으로 받는 관측이므로 오히려 정통으로 겨냥해야 할 대상이다.

cross-view 실증: (latent 1, view 1) 픽셀을 교란하면 teacher 타깃이 view1=0.60 vs view0/2=0.07로 움직인다. 1:1 대응이 지배적이면서 다른 뷰도 함께 움직인다 = teacher 내부 global attention(24개 중 19개가 full global)이 cross-view 정보를 타깃에 실어 넘긴다는 직접 증거. multi-view는 loss 배선이 아니라 teacher가 만든다.

3 결과

3.1 학습 (job 74356→74649→74860, 총 20h49m)

max_steps=20000 reached, preempt 2회 모두 자동 복구(손실 80 step + 0 step), NaN 0, rank 파일 8개.

최종 25개 로그 지점 평균 (step 19,519–19,999) arm A video 0.1316 action 0.0201 proprio 0.0055 arm B video 0.1221 action 0.0187 proprio 0.0052 arm C video 0.1314 action 0.0193 proprio 0.0053 repa_ang −0.8924 repa_scale 1.644 정렬 궤적: cos 0.04 → 0.85 (1,000 step) → 0.89 (수렴). repa_scale 7.56 → 1.64 (−78%) 속도: A 0.374 / B 0.287 / C 0.283 it/s → arm C는 arm B와 같은 wall-clock 예산
REPA는 픽셀 예측을 개선하지 않는다 (C 0.1314 vs A 0.1316). 이건 예상된 결과이자 좋은 신호다 — arm C의 가설은 “픽셀을 더 잘 예측한다”가 아니라 “같은 픽셀 품질에서 표현이 기하를 담는다”이고, 값은 SR로 나와야 한다.

3.2 평가 (24 task × 50 rollout)

subsetnarm A
no depth
arm B
+1.64B depth
arm C
+29M REPA
ALL (24)120061.08%66.00%64.67%
PnP (8)40044.00%53.75%46.75%
non-PnP (16)80069.62%72.12%73.62%

3.3 ⚠ 유의성 — 여기가 핵심이다

subset비교차이 (%p)SEz95% CI판정
ALLB−A+4.921.962.51[+1.07, +8.76]유의
ALLC−A+3.581.971.82[−0.28, +7.45]미확립
ALLB−C+1.331.940.69[−2.47, +5.14]미확립
PnPB−A+9.753.522.77[+2.86, +16.64]유의
PnPB−C+7.003.531.98[+0.09, +13.91]유의(경계)
PnPC−A+2.753.520.78[−4.15, +9.65]미확립
non-PnPC−A+4.002.251.78[−0.41, +8.41]미확립
non-PnPB−C−1.502.22−0.67[−5.86, +2.86]노이즈
폐기한 해석: 결과를 처음 보고 “PnP는 explicit depth가, non-PnP는 REPA가 산다”는 이중 해리를 주장하려 했으나 통계가 지지하지 않는다 — non-PnP의 C−B는 z=−0.67로 순수 노이즈다. 매력적인 서사였지만 근거가 없다.
확립된 것 셋: ① B > A (전체, z=2.51) ② B > A (PnP, z=2.77) ③ B > C (PnP, z=1.98).

4 Takeaway

표현이 기하를 담는 것과, 그 기하가 action head에 전달되는 것은 별개다

arm C는 VGGT-Ω와 코사인 0.89로 정렬됐다. 정렬 자체는 확실히 학습됐고 1,000 step에 이미 0.85에 도달했다. 그런데 PnP에서 explicit depth 생성에 7.00%p 뒤진다(z=1.98). 집기·놓기가 요구하는 공간 정밀도는 표현 정렬만으로 오지 않는다는 뜻이다.

이건 REPA 계열 방법론에 대한 구체적인 제약 조건이고, “정렬 지표가 좋아졌다”를 성능 근거로 쓰는 관행에 대한 반례이기도 하다.

지금 결론의 병목은 방법이 아니라 표본이다. arm C > arm A는 +3.58%p로 부호가 전체·PnP·non-PnP 모두에서 일관되게 양수지만 z=1.82로 95%에 못 미친다. 50 rollout/task에서는 SE가 약 2%p라 이 크기의 효과를 가릴 수 없다.
효율 관점의 사실: 파라미터 1/57(29M vs 1.64B)로 SR 이득의 73%를 가져온 것은 점추정으로는 사실이며, wall-clock 예산도 arm B와 동일하다(0.283 vs 0.287 it/s). 다만 이 73%에는 위의 불확실성이 그대로 실려 있다.

5 Next Steps

1. [최우선] 100 rollout/task 재평가 — arm A · arm C. SE가 1.97 → 약 1.4%p로 줄어 +3.58이 z≈2.6이 된다. 8 GPU × 약 1.5h × 2 arm. 릴리스 ckpt에서 50/task 75.8% vs 100/task 75.3%로 −0.5%p 수렴한 이력이 있어 신뢰할 만하다.

2. C0 ablation — repa_frames = cond vs gen. 관측 정렬(Spatial Forcing)과 생성 정렬(Geometry Forcing) 중 무엇이 SR을 사는가. 같은 백본·teacher·레시피에서 둘을 직접 비교한 선행 연구가 없다. all은 720 토큰에 신호를 나눠 실어 어느 쪽도 충분히 밀지 못했을 수 있다 — 실측 프레임당 gradient: all 1.66e-4 / gen 2.49e-4 / cond 4.97e-4. PnP가 요구하는 것이 현재 관측의 정밀한 3D라면 cond가 답일 수 있다.

3. λ_scale 스윕 (C4). 최종 repa_scale 1.644 × 0.05 = 0.082로 video_loss(0.131)의 63%. GF의 0.05는 그쪽 teacher feature 스케일 기준이라 우리 teacher에 맞는다는 보장이 없다.

4. relational loss (C2). PAIWorld와 MECo-WAM이 독립적으로 둘 다 anchor 기반 관계 정렬을 택했다. dense 정렬이 약하다는 신호일 수 있고, 이번 PnP 실패가 그 증거일 수 있다.

5. frozen probe. arm A·C에는 depth 출력이 없으므로 네 arm을 공통 3D 축에 올릴 유일한 수단. 미착수.

6 이번에 밟은 함정 (재발 방지)

#함정왜 안 보였나
1vae_stride: (4, 16, 16)는 YAML에서 문자열이라 [0]'('num_frames_per_latent가 아무도 안 쓰던 dead assignment였다. REPA가 첫 소비자
2DeepSpeedStrategy는 step을 torch.autocast로 감싸지 않는다. DeepSpeed가 파라미터를 직접 캐스팅 → dtype을 맞춰줄 주체가 없음(bf16 param, fp32 activation) 조합에서만 터진다. 활성값을 projector dtype으로 명시 캐스팅해야 함
3elementwise_affine=False근본 수정이 아니었다실패가 LayerNorm에서 Linear로 옮겨갔을 뿐(mat1 and mat2 must have the same dtype)
4stub 테스트가 실제 조건을 대신 채우면 그 조건은 검증되지 않는다 — 3회 연속 놓침①값 하드코딩 ②DeepSpeed 밖 fp32 ③bf16을 autocast 안에서 실행(= 안전한 조합만 테스트)
5$((0020000))은 8진수로 8192가 된다(조용히)[ x -ge y ]는 10진수라 안전. step이 zero-padded로 로깅됨
6격리 벤치마크가 실제 비용을 2배 과소평가 — “7.9% 세금”으로 보고했으나 실제 1.32×accum=4라 optimizer step당 4회 + 8-rank 경합. arm 간 같은 step의 speed 비교가 정답이었다
7평가를 sbm으로 제출하면 preempt 시 재개가 없다arm C 평가가 23/24에서 잘림. 평가도 sbmr을 쓸 것
부수 산출물: scripts/eval_robocasa.shEVAL_RANKS(개별 태스크 재실행 — 이번에 두 번 썼다) · tmp/compare_arms.py(N-arm 비교, 모든 summary에 있는 태스크만 집계) · tmp/autoeval_armC.sh(완주를 sacct가 아닌 로그 최대 step으로 판정) · tmp/test_repa_plumbing.py(3 모드 × 3 dtype).