NUM_ENVS=1로 재실행 → 75%, 세션 리셋 3회(에피소드 경계만)/healthz는 통하지 않는다 — rank 0의 RoboarenaServer엔 라우트가 없어 426 Upgrade Required. TCP 폴백이 분기점이었다job 51168 (NUM_ENVS=4): 1/4 = 25.0% [95% CI 5.3–71.6]. 낮은 성공률을 정책 한계로 읽기 쉬운 지점이었다. 서버 로그가 답을 줬다.
RoboLab 클라이언트는 env마다 고유 UUID를 발급하지만(policies/dreamzero/client.py:162), 서버는 _current_session_id 하나만 추적하고 값이 바뀌면 _reset_state()로 temporal history를 폐기한다(socket_test_optimized_AR.py:77, 256-260).
4개 env가 동시 진행하면 요청이 교대로 들어와 매 추론 호출마다 맥락이 초기화된다. DreamZero는 과거 프레임으로 미래를 상상하는 world model이므로 이 조건에서는 정상 동작이 불가능하다.
예측 영상에도 그대로 반영됐다 — 108개 mp4가 전부 _n1(누적 청크 1개)인 ~96KB 조각이었다. 비교 분석에 쓸 수 없는 상태.
| job | 설정 | 성공률 | 세션 리셋 | 예측 mp4 |
|---|---|---|---|---|
| 51168 | NUM_ENVS=4 | 1/4 = 25.0% | 107 | 108개 _n1 조각 |
| 51212 | NUM_ENVS=1 NUM_RUNS=4 | 3/4 = 75.0% | 3 | 4개 (_n21 _n35 _n14 _n31) |
세션 리셋 3회는 에피소드 4개 사이의 전환 3회와 정확히 일치한다. 에피소드별로는 run0 성공(434 steps) / run1 실패(750 timeout) / run2 성공(295) / run3 성공(668).
NUM_ENVS=1 제약 때문에 --num-envs 10이나 adaptive 프로토콜(CI 폭 ≤0.14)을 쓸 수 없어, 검정력을 올리려면 NUM_RUNS를 키워 시간을 배로 써야 한다.
/healthz가 통하지 않는다426 Upgrade Required는 WebSocket 엔드포인트에 평범한 HTTP GET을 날렸을 때 나온다. _health_check(socket_test_optimized_AR.py:733)는 WebsocketPolicyServer에만 물려 있고 rank 0이 실제로 띄우는 RoboarenaServer엔 없다. cosmos3처럼 /healthz 200만 기다렸다면 서버가 멀쩡한데도 30분 타임아웃으로 실패했을 것이다.
DreamZero는 액션과 비디오를 함께 예측하므로, 두 영상을 시간 정렬하면 실패를 "상상이 틀렸나 / 상상은 맞았는데 행동이 틀렸나"로 가를 수 있다. 정렬은 청크 크기를 가정하지 않고 두 비디오 길이의 선형 매핑으로 한다 — 실측 청크 cadence(~21 sim step)가 action_horizon=24와 어긋나기 때문.
| 성공 (run2) | 실패 (run1) | |
|---|---|---|
| 예측 vs 실제 일치도 | 높음 | 높음 |
| 파지가 예측에 나타남 | ✅ 바나나가 그리퍼에 물림 | ❌ |
| 목표 접근이 예측에 나타남 | ✅ 아직 안 보이는 그릇이 예측에 등장 | ❌ |
| 시간 경과 | 파지 → 그릇 이동 | t=25s와 t=45s가 거의 동일, 정체 |
실패는 인식/월드모델 문제가 아니다. 모델은 장면을 정확히 파악하고 있고, 자기가 바나나를 못 잡고 있다는 것까지 정확히 예측한다. 문제는 그 상태를 알면서도 벗어나는 행동을 생성하지 못한다는 것 — 파지 실패 후 복구 행동이 없어 750스텝을 정체한다.
world-action model에서 "상상은 맞는데 행동이 틀리다"는 분리가 실제로 관측된 사례다. 단, 프레임 3~4개 근거의 잠정 진단이다.
num_envs=1은 우회이지 해결이 아니다. 서버가 세션별 상태를 분리하지 않는 한 병렬 평가가 불가능하고, 이는 통계적 검정력에 직접 영향을 준다.pretrained_path: null을 "가중치 통합됨 → 별도 다운로드 불필요"로 읽었는데 틀렸다. 실제로는 HF hub에서 Wan2.1 base 28GB를 받아온다. 공유 캐시에 이미 있어 안 막혔을 뿐이다.achieved 값 확인 — 파지 성공의 무료 지표(0.37 정지 = 물었음, 1.0 = 허공). 실패가 파지 실패인지 파지 후 낙하인지 확정SUITE=smoke → SUITE=standard(15 태스크)로 cosmos3와 동일 조건 비교. --qos=own 필수 (다중 시간 규모, extra는 preempt됨)run_*.hdf5에 물체 실제 위치(banana/root_pose, bowl/root_pose)가 그대로 있다. 영상 프레임 3~4개로 내린 진단을 이걸로 검증했더니 두 번 뒤집혔다.
여러 번 성공적으로 집었고 재시도도 계속했다. "파지 실패"도 "복구 행동 부재"도 아니었다. 영상에서 본 "정체 상태"는 놓친 직후의 순간을 포착한 것이었다.
run1에서 그리퍼가 급변한 직후 낙하하는 사례를 찾았다 (step 503→504: 0.75 → 0.02, 정확히 청크 경계). 여기서 "청크 재생성 시 그리퍼 연속성이 깨져 실패한다"고 결론낼 뻔했으나 4개 run을 모두 집계하자 반례가 나왔다.
| run | 결과 | 낙하 | 그리퍼 급변 | z_end |
|---|---|---|---|---|
| 0 | 성공 | 1 | 1 | 0.076 |
| 1 | 실패 | 6 | 3 | 0.012 |
| 2 | 성공 | 0 | 0 | 0.096 |
| 3 | 성공 | 4 | 7 | 0.112 |
z_end바나나 시작 높이는 0.021(테이블 위). 성공 3건은 0.076 / 0.096 / 0.112(그릇 안 높이)로 끝나는데, 실패 1건만 0.012 — 시작보다도 낮다.
z_end 분포를 확대해 판정해야 한다.
표본이 2.5배 차이나므로 cosmos3를 태스크당 4개로 20,000회 무작위 추출해 동일 조건으로 맞췄다.
양쪽 다 조기 종료가 없다. 문제는 "못 한다"가 아니라 "시간 내 못 끝낸다"이다.
"파지 불안정 → 시도 반복 → timeout"을 먼저 검증했으나 반증됐다. 스텝당 정규화하면 낙하가 오히려 실패 쪽이 낮다(1.34 vs 성공 1.92 / 1000 steps). raw 값이 커 보인 건 에피소드가 길어서다.
태스크별로 분해하자 정반대 성격의 두 유형이 드러났다. 앞선 집계에서 신호가 없던 건 둘이 상쇄됐기 때문이다.
| 유형 | 태스크 | lifts | drops | 성공 |
|---|---|---|---|---|
| A 못 듦 | PickUpBluePitcher | 0.0 | 0.0 | 0/4 |
| ReorientAllMugs | 0.2 | 0.2 | 0/4 | |
| ReorientJug | 0.2 | 0.0 | 0/4 | |
| CookingPickPastaTool | 0.2 | 0.2 | 0/4 | |
| B 놓침 | BlockStackingSpecifiedOrder | 3.2 | 2.5 | 0/4 |
| RubiksCubesInBin | 2.5 | 2.0 | 0/4 | |
| BlockStackingOrderAgnostic | 2.2 | 2.0 | 0/4 | |
| Stack3RubiksCube | 2.0 | 1.5 | 0/4 | |
| 성공 | BananasInBinOneMore | 1.2 | 0.2 | 4/4 |
| MarkerInMug | 1.0 | 0.0 | 3/4 | |
| RubiksCubeLeftOfBowl | 1.0 | 0.5 | 3/4 |
들지 못하는 물체가 pitcher · mug · jug로 전부 손잡이가 달린 용기다. 잡히는 물체는 banana · block · rubiks cube 같은 단순 형태다.
교차 검증: MarkerInMugTask는 물체 12개로 씬이 복잡한 축인데도 3/4 성공한다. 머그를 잡지 않고 마커를 넣는 태스크라서다. 즉 씬 복잡도가 아니라 파지 대상의 형태가 갈림길이며, 이 교차 검증이 복잡도라는 대안 설명을 배제한다.
유형 B는 전부 스태킹/정밀 배치로, 놓는 동작의 정밀도가 요구되는 태스크다.
지금까지 평가는 전부 2-view였다 — 어댑터가 두 번째 exterior를 np.zeros_like(검은 화면)로 채운다(client.py:147). cosmos3는 3-view를 다 쓰므로 42.0% vs 26.7% 비교는 입력 조건이 어긋나 있었다. CAM2_SOURCE=right로 3-view n=10 재실행해 조건을 맞췄다.
PickUpBluePitcher는 3-view로도 0/10 — "깊이 단서 부족으로 손잡이 물체를 못 든다"는 앞선 가설이 무너졌다. 유형 A는 시점 수 문제가 아니다.
| task | DZ 3v | DZ 2v | cosmos3 |
|---|---|---|---|
| BananasInBinOneMore | 10/10 | 4/4 | 10/10 |
| RubiksCubeLeftOfBowl | 10/10 | 3/4 | 9/10 |
| RubiksCubeOrBanana | 9/10 | 2/4 | 10/10 |
| RubiksCubesInBin | 6/10 | 0/4 | 10/10 |
| BananaInBowl | 4/10 | 2/4 | 10/10 |
| Stack3RubiksCube | 3/10 | 0/4 | 1/10 |
| MarkerInMug | 2/10 | 3/4 | 5/10 |
| PickUpBluePitcher | 0/10 | 0/4 | 1/10 |
| RedItemsInBin | 0/10 | 2/4 | 1/10 |
| ReorientJug | 0/10 | 0/4 | 3/10 |
| 그 외 5 (block×2, cooking, raisin, reorient-mugs) | 0/10 | 0/4 | 0~3/10 |
extra QOS라 3번 preempt됐고, RUN_TAG=$SLURM_JOB_ID라 requeue마다 0부터 재시작해 133 에피소드를 낭비했다. RoboLab은 같은 --output-folder-name이면 끝난 run을 건너뛴다(runner.py:79) — 고정 RUN_TAG + 부분결과 시딩으로 남은 17개만 돌려 완주했다. preemptible 배치 평가는 lineage 전체가 같은 출력 폴더를 써야 한다.