Index
2026-08-19 — Experiment (v3, horizon 스윕)

FD Replay — World Model은 정책 실패를 미리 보는가

Cosmos3 | 정책이 실행한 액션을 base Cosmos3-Nano forward-dynamics에 teacher-forcing · 32 episodes (16 fail / 16 success) × 재접지 주기 4수준 · 전 에피소드 4-panel 영상

TL;DR

13/16
실패 재현 @8.53s
0
놓친 실패 (전 조건)
93%
outcome 정확도 @4.27s
8/16
성공 재현 @8.53s
~7s
유효 예측 지평

1 질문과 설계

정책의 imagination은 action과 video를 공동 생성하므로(policy 모드) 자기가 의도한 미래를 그릴 뿐 물리 예측 책임이 없다. base Cosmos3-Nano의 forward-dynamics 모드는 실제 실행된 액션을 조건으로 강제받는다. 정책이 실패한 에피소드의 액션을 그대로 되먹여, WM이 그 실패를 그리는지 본다.

joints[T,7] ──Franka modified-DH FK──▶ panda_link8 ──@DROID_TO_OPENCV──▶ ──pose_abs_to_rel(rot6d, backward_framewise)──▶ 9D delta + (1−gripper_cmd) = [16,10]/chunk ──quantile normalize──▶ fd action spec (학습 droid_lerobot_dataset.py와 동일 규약) 1 chunk = 16 액션 = 16프레임 = 1.067s · 윈도우 = first gripper close −32스텝부터 최대 8 chunks(8.53s) 재접지 주기 N: 실제 프레임을 N chunk마다 재주입 → 모델이 한 번에 외삽하는 시간 = N × 1.067s N=1(regrounded) · N=2 · N=4 · N=8(open_loop, t=0에 한 번만) 모델: base Cosmos3-Nano, UniPC 30 steps, shift=10 · 잡 85061/85062/85446+85582/85447

판정state: 윈도우 종료 시점의 최종 조작 상태(무엇을 쥐고/놓고 있는가)가 실제와 같은가 (match / under-commit / object lost). 전체 composite(wrist + 외부 2뷰) 기준, 단일 평가자.

2 결과 — horizon 스윕

0%25%50%75%100% 거의 자명 (§3.5) 실패 13/16 성공 8/16 전체 84% 실패 에피소드 (평탄) 성공 에피소드 (붕괴) 1.07sN=12.13sN=24.27sN=48.53sN=8 재접지 주기 = 모델이 한 번에 외삽하는 시간 최종 조작 상태 일치율
Figure 1: 재접지 주기(=1회 외삽 시간) 대비 최종 조작 상태 일치율. 빨강=실패 에피소드, 파랑=성공 에피소드, 점선=전체. 실패는 평탄, 성공은 붕괴.
조건 (1회 외삽 시간)state match실패 16건성공 16건outcome 정확도 (결정가능)
N=1 — 1.07s32/32 (100%)16/1616/1632/32 (100%)
N=2 — 2.13s31/32 (97%)16/1615/1631/31 (100%)
N=4 — 4.27s27/32 (84%)13/1614/1627/29 (93%)
N=8 — 8.53s21/32 (66%)13/168/1621/25 (84%)
실패 신호는 horizon에 강건하다: 1.07s에서 8.53s로 8배 늘려도 실패 재현은 16/16 → 13/16으로만 떨어지고, 실패를 성공으로 그린 사례는 어떤 조건에서도 0건이다. 실패 감지기로서 recall이 높다.
성공 신호는 무너진다: 같은 구간에서 성공 재현은 16/16 → 8/16. 실패한 8건 중 4건은 "실제로는 배치·투하를 마쳤는데 아직 들고 있음"(under-commit), 4건은 물체 소멸이다. 즉 오래 상상시킬수록 모든 것을 미완료로 보는 쪽으로 쏠린다.
왜 비대칭인가: 실패는 대개 "물체가 안 움직이거나 계속 들려 있는" 저변화 상태라 관성적 예측이 자동으로 정답이 된다. 반면 성공은 정확한 타이밍의 접촉·해제를 요구한다. 실패 recall이 높은 것은 물리 이해와 예측의 보수성이 같은 방향을 가리킨 결과이기도 하다 — 이 교란은 동적 실패만 따로 재보면 분리된다(§6).

3 "재접지는 답을 보여준 것 아닌가?" — leakage 정량화

지적은 옳다. N=1은 매 chunk 시작마다 실제 프레임을 8번 주입하므로 모델은 한 번에 1.07초만 외삽하고, 판정한 최종 프레임은 마지막 실제 프레임에서 겨우 16프레임 뒤다. 그 사이에 조작 상태가 바뀌는 일은 드물어 N=1의 32/32는 outcome 지표로서 거의 자명하다. 그래서 N을 늘려가며 다시 쟀고, 위 표의 N=4 / N=8이 그 답이다.

얼마나 자명한지는 persistence baseline(조건 프레임을 그대로 복사)으로 잰다. 지표는 LPIPS(wrist 뷰, 낮을수록 실제와 유사).

N=1 모델 오차
0.2137
N=1 복사(persistence)
0.3005
복사 대비 개선
+28.9%
완전한 복사는 아니다: 1.07초 구간에서 모델은 복사보다 29% 정확하다 — 팔과 물체의 실제 움직임을 만든다. 다만 이건 "픽셀 동역학을 그린다"는 뜻이지 "결과를 예측한다"는 뜻이 아니다. 두 주장은 분리해야 한다.
0.00.10.20.30.40.50.6 N=8 (open-loop)N=4N=2 persistence (복사) 1.072.133.204.275.336.407.478.53 마지막 실제 프레임 이후 경과 시간 (초) LPIPS (낮을수록 정확)
Figure 2: 마지막 실제 프레임 이후 경과 시간 대비 LPIPS. 재접지 주기가 달라도 곡선이 겹친다 — 열화는 에피소드 진행도가 아니라 경과 horizon의 함수다. 회색 점선은 persistence.
경과 horizonopen-loop 모델persistence(첫 프레임)개선폭
1.07s0.15940.2728+41.6%
2.13s0.25220.3585+29.7%
3.20s0.34170.4051+15.7%
4.27s0.41650.4670+10.8%
5.33s0.46780.5038+7.1%
6.40s0.49470.5224+5.3%
7.47s0.49740.5089+2.3%
8.53s0.51410.4862-5.7%
교차점: 8.53초에서 모델은 persistence보다 −5.7% — "아무 일도 안 일어났다고 가정"하는 것보다 못하다. 유효 예측 지평은 7초 안팎이고, N=8 조건은 이미 그 경계 밖이다. 반대로 N=4(4.27s)는 경계 안이며 그 지점의 outcome 정확도 93%는 복사로 설명되지 않는다(같은 지점 LPIPS 우위 +11.9%).
누적이 원인: N=1의 오차는 chunk 위치가 0→7로 가도 0.158→0.192로 평탄하다. open-loop 열화는 과제 난이도가 아니라 전적으로 오차 누적이다.

4 gripper는 들어가는가? — 들어간다

fd 액션 10차원의 마지막 채널이 gripper 명령이다(모델 공간 1−g, 정규화 후 open=+1 / closed=−1). 전 32 에피소드에서 window step 32에 정확히 open→closed로 토글하고 재파지·릴리즈까지 실린다. 아래 영상 하단 스트립이 매 프레임 WM에 들어간 gripper 명령이다.

다만 오래 상상하면 덜 쓴다: RubiksCubesInBin env1[06]은 gripper가 chunk5에서 OPEN으로 열려 실제로는 큐브를 bin에 투하했는데, N=8 예측은 계속 쥔 채로 간다. 같은 에피소드가 N=2에서는 투하를 정확히 재현한다 — 즉 release를 무시하는 관성은 모델의 고정된 편향이 아니라 누적 drift의 증상이다.
[06] 왼쪽부터 실제 / N=1 / N=4 / N=8. N=8만 큐브를 놓지 못한다.
[12] 실패(병이 bin 옆에 누움)를 N=8에서도 8.5초 내내 재현한 사례.

5 전체 영상 갤러리 (32 에피소드 × 4조건)

각 영상 = [ 실제 SIM | WM N=1 (1.07s) | WM N=4 (4.27s) | WM N=8 (8.53s) ], 15 Hz 공통 시계. 패널 위 파란 눈금은 그 조건이 실제 프레임을 재주입받은 시점, 하단 스트립은 매 프레임 gripper 명령(초록=OPEN, 빨강=CLOSED). 왼쪽에서 오른쪽으로 갈수록 "모델이 혼자 상상한 시간"이 길어진다.

RubiksCubeRightOfBowl

[00] cfgoff_RubiksCubeRightOfBowl_env0
REAL: FAIL  N=2 match N=4 object lost N=8 object lost
큐브가 파란 blob으로 변형
[01] cfgoff_RubiksCubeRightOfBowl_env1
REAL: FAIL  N=2 match N=4 match N=8 match
큐브 파지 상태 유지
[02] cfgoff_RubiksCubeRightOfBowl_env4
REAL: SUCCESS  N=2 match N=4 match N=8 under-commit
큐브가 빨간 그릇 위에 배치됨 — 8.5s에선 실패했던 판정
[03] cfgon_RubiksCubeRightOfBowl_env2
REAL: SUCCESS  N=2 match N=4 match N=8 under-commit
큐브 그릇 위 배치 재현 — 8.5s에선 실패

RubiksCubesInBin

[04] cfgoff_RubiksCubesInBin_env0
REAL: FAIL  N=2 match N=4 match N=8 match
파란 큐브 + 주변 배치까지 일치
[05] cfgoff_RubiksCubesInBin_env5
REAL: FAIL  N=2 match N=4 match N=8 match
주황 큐브 파지(약간 반투명)
[06] cfgoff_RubiksCubesInBin_env1
REAL: SUCCESS  N=2 match N=4 under-commit N=8 under-commit
실제는 bin 투하, 예측은 계속 쥠 (8.5s와 동일한 유일 케이스)
[07] cfgoff_RubiksCubesInBin_env7
REAL: SUCCESS  N=2 object lost N=4 object lost N=8 object lost
큐브 소멸 (유일한 불일치)

StackWhiteMugs

[08] cfgoff_StackWhiteMugs_env0
REAL: FAIL  N=2 match N=4 match N=8 match
머그 테이블 잔류 상태 일치
[09] cfgoff_StackWhiteMugs_env1
REAL: FAIL  N=2 match N=4 match N=8 object lost
빈 그리퍼 상태는 일치하나 물체 정체성 교체(marginal)
[10] cfgoff_StackWhiteMugs_env5
REAL: SUCCESS  N=2 match N=4 match N=8 under-commit
머그 배치 완료 재현 — 8.5s에선 실패
[11] cfgon_StackWhiteMugs_env2
REAL: SUCCESS  N=2 match N=4 match N=8 object lost
머그 2개 적재 재현 — 8.5s에선 소멸

MustardInRightBin

[12] cfgoff_MustardInRightBin_env3
REAL: FAIL  N=2 match N=4 match N=8 match
병이 bin 옆에 누운 실패 재현
[13] cfgoff_MustardInRightBin_env6
REAL: FAIL  N=2 match N=4 match N=8 match
병 파지 상태 일치
[14] cfgoff_MustardInRightBin_env2
REAL: SUCCESS  N=2 match N=4 match N=8 object lost
병 파지 재현 — 8.5s에선 소멸
[15] cfgoff_MustardInRightBin_env4
REAL: SUCCESS  N=2 match N=4 match N=8 object lost
병 파지 재현 — 8.5s에선 소멸

GreenSpoonsInPot

[16] cfgoff_GreenSpoonsInPot_env0
REAL: FAIL  N=2 match N=4 match N=8 match
주걱 파지
[17] cfgoff_GreenSpoonsInPot_env1
REAL: FAIL  N=2 match N=4 match N=8 match
주걱 파지
[18] cfgoff_GreenSpoonsInPot_env2
REAL: SUCCESS  N=2 match N=4 match N=8 match
주걱 파지
[19] cfgon_GreenSpoonsInPot_env8
REAL: SUCCESS  N=2 match N=4 match N=8 match
주걱 파지

BowlStackingRightOnLeft

[20] cfgoff_BowlStackingRightOnLeft_env1
REAL: FAIL  N=2 match N=4 object lost N=8 object lost
그릇 1개가 blob으로 뭉개짐
[21] cfgoff_BowlStackingRightOnLeft_env7
REAL: FAIL  N=2 match N=4 under-commit N=8 match
실제는 그릇 미접촉, 예측은 그릇을 든 상태(marginal)
[22] cfgoff_BowlStackingRightOnLeft_env5
REAL: SUCCESS  N=2 match N=4 match N=8 match
그릇 기울인 파지 일치
[23] cfgoff_BowlStackingRightOnLeft_env8
REAL: SUCCESS  N=2 match N=4 match N=8 match
그릇 파지 일치

FruitsOnionToPlate

[24] cfgoff_FruitsOnionToPlate_env1
REAL: FAIL  N=2 match N=4 match N=8 match
호박 파지 + 과일 배치 일치
[25] cfgoff_FruitsOnionToPlate_env2
REAL: FAIL  N=2 match N=4 match N=8 match
라임·오렌지 배치 거의 정확
[26] cfgoff_FruitsOnionToPlate_env0
REAL: SUCCESS  N=2 match N=4 match N=8 match
양파 접시 배치 일치
[27] cfgoff_FruitsOnionToPlate_env8
REAL: SUCCESS  N=2 match N=4 match N=8 match
석류 접시 배치 일치(물체 중복 약간)

FoodPacking1Cans

[28] cfgoff_FoodPacking1Cans_env0
REAL: FAIL  N=2 match N=4 match N=8 match
캔 테이블 잔류 재현
[29] cfgoff_FoodPacking1Cans_env1
REAL: FAIL  N=2 match N=4 match N=8 match
캔 파지 상태 일치(라벨 변형)
[30] cfgon_FoodPacking1Cans_env1
REAL: SUCCESS  N=2 match N=4 match N=8 match
캔 파지 일치
[31] cfgon_FoodPacking1Cans_env8
REAL: SUCCESS  N=2 match N=4 match N=8 match
캔 파지 일치

에피소드별 판정 (n=32)

episode실제N=1N=2N=4N=8비고
[00] cfgoff_RubiksCubeRightOfBowl_env0Fmatchmatchobject lostobject lost큐브가 파란 blob으로 변형
[01] cfgoff_RubiksCubeRightOfBowl_env1Fmatchmatchmatchmatch큐브 파지 상태 유지
[02] cfgoff_RubiksCubeRightOfBowl_env4Smatchmatchmatchunder-commit큐브가 빨간 그릇 위에 배치됨 — 8.5s에선 실패했던 판정
[03] cfgon_RubiksCubeRightOfBowl_env2Smatchmatchmatchunder-commit큐브 그릇 위 배치 재현 — 8.5s에선 실패
[04] cfgoff_RubiksCubesInBin_env0Fmatchmatchmatchmatch파란 큐브 + 주변 배치까지 일치
[05] cfgoff_RubiksCubesInBin_env5Fmatchmatchmatchmatch주황 큐브 파지(약간 반투명)
[06] cfgoff_RubiksCubesInBin_env1Smatchmatchunder-commitunder-commit실제는 bin 투하, 예측은 계속 쥠 (8.5s와 동일한 유일 케이스)
[07] cfgoff_RubiksCubesInBin_env7Smatchobject lostobject lostobject lost큐브 소멸 (유일한 불일치)
[08] cfgoff_StackWhiteMugs_env0Fmatchmatchmatchmatch머그 테이블 잔류 상태 일치
[09] cfgoff_StackWhiteMugs_env1Fmatchmatchmatchobject lost빈 그리퍼 상태는 일치하나 물체 정체성 교체(marginal)
[10] cfgoff_StackWhiteMugs_env5Smatchmatchmatchunder-commit머그 배치 완료 재현 — 8.5s에선 실패
[11] cfgon_StackWhiteMugs_env2Smatchmatchmatchobject lost머그 2개 적재 재현 — 8.5s에선 소멸
[12] cfgoff_MustardInRightBin_env3Fmatchmatchmatchmatch병이 bin 옆에 누운 실패 재현
[13] cfgoff_MustardInRightBin_env6Fmatchmatchmatchmatch병 파지 상태 일치
[14] cfgoff_MustardInRightBin_env2Smatchmatchmatchobject lost병 파지 재현 — 8.5s에선 소멸
[15] cfgoff_MustardInRightBin_env4Smatchmatchmatchobject lost병 파지 재현 — 8.5s에선 소멸
[16] cfgoff_GreenSpoonsInPot_env0Fmatchmatchmatchmatch주걱 파지
[17] cfgoff_GreenSpoonsInPot_env1Fmatchmatchmatchmatch주걱 파지
[18] cfgoff_GreenSpoonsInPot_env2Smatchmatchmatchmatch주걱 파지
[19] cfgon_GreenSpoonsInPot_env8Smatchmatchmatchmatch주걱 파지
[20] cfgoff_BowlStackingRightOnLeft_env1Fmatchmatchobject lostobject lost그릇 1개가 blob으로 뭉개짐
[21] cfgoff_BowlStackingRightOnLeft_env7Fmatchmatchunder-commitmatch실제는 그릇 미접촉, 예측은 그릇을 든 상태(marginal)
[22] cfgoff_BowlStackingRightOnLeft_env5Smatchmatchmatchmatch그릇 기울인 파지 일치
[23] cfgoff_BowlStackingRightOnLeft_env8Smatchmatchmatchmatch그릇 파지 일치
[24] cfgoff_FruitsOnionToPlate_env1Fmatchmatchmatchmatch호박 파지 + 과일 배치 일치
[25] cfgoff_FruitsOnionToPlate_env2Fmatchmatchmatchmatch라임·오렌지 배치 거의 정확
[26] cfgoff_FruitsOnionToPlate_env0Smatchmatchmatchmatch양파 접시 배치 일치
[27] cfgoff_FruitsOnionToPlate_env8Smatchmatchmatchmatch석류 접시 배치 일치(물체 중복 약간)
[28] cfgoff_FoodPacking1Cans_env0Fmatchmatchmatchmatch캔 테이블 잔류 재현
[29] cfgoff_FoodPacking1Cans_env1Fmatchmatchmatchmatch캔 파지 상태 일치(라벨 변형)
[30] cfgon_FoodPacking1Cans_env1Smatchmatchmatchmatch캔 파지 일치
[31] cfgon_FoodPacking1Cans_env8Smatchmatchmatchmatch캔 파지 일치

6 Takeaway / 한계 / Next

질문에 대한 답

"실패한 예시를 world model에 넣으면 실패한다고 예측하나?" → 예, 그리고 그 신호는 leakage 때문이 아니다. 4.27초를 혼자 상상하게 해도 실패 13/16을 미완료로 그리고 outcome 정확도는 93%다. 어떤 조건에서도 실패를 성공으로 그리지 않았다.

대신 반대 방향으로 틀린다. 오래 상상할수록 완료 이벤트를 놓쳐 모든 것을 미완료로 본다(성공 재현 16/16→8/16). 실패 감지기로 쓰면 recall은 높고 precision이 떨어진다 — 성공한 롤아웃도 "아직 안 끝났다"고 부른다.

실용 결론: WM 기반 평가·실패 감지는 2–4초 재접지 구간에서 설계하면 된다(그 구간 outcome 93–100%). 8초 이상 순수 상상은 물체 정체성 유지 자체가 안 되므로 쓰지 않는다.

한계

n=32, 단일 평가자·최종 프레임 기준 육안 판정(초기 v1에서 실제 오판이 발생해 전면 재판정한 이력이 있다). 실패의 저변화 성격이 recall을 부풀렸을 가능성이 남는다. base Nano는 실사 DROID 학습이라 sim 렌더가 OOD — open-loop drift에 도메인 갭이 섞여 물리 한계와 분리되지 않는다. seed 1개.

다음 실험

동적 실패만 따로 recall 재측정 — 물체를 떨어뜨림·쓰러뜨림처럼 상태가 크게 변하는 실패만 골라야 "관성 예측이 우연히 맞은 것"과 분리된다(§2 교란 제거). ② VLM judge 자동화 + 남은 467 usable 에피소드로 스케일. ③ N=3, N=6을 채워 붕괴 지점을 좁히기. ④ seed ensemble 분산을 실패 신호로 쓸 수 있는지. ⑤ sim 영상으로 fd 경량 fine-tune 후 붕괴율 재측정.

스크립트: scripts/fd_replay_prep.py · fd_replay_run.py(--reground-every N) · fd_replay_horizon_video.py · fd_replay_report.py 데이터: tmp/fd_replay/(prep|gen|horizon|judge)/ · 판정: judge/judgments_all.json 잡: 85061(N=8) 85062(N=1) 85446+85582(N=2) 85447(N=4) — --container=nvcr.io/nvidia/cuda:12.8.0-devel-ubuntu22.04 필수