success/(261 ep · 126,728 프레임) + failure/(1,639 ep · 2,525,711 프레임), 54.6 GB, per-view h264(GOP 8). NaN trace 3 ep 발견·제외. 변환은 CPU sbatch 2샤드 × 30 worker, ~15분/샤드.augment="bc"(1.4 s/샘플, 8 worker 9 samples/s) · OMP_NUM_THREADS=1 · worker 10 · -c 48.플랜 Phase 0을 최단 경로로 끝내고 FT-mix(성공+실패)를 own 4 GPU에 먼저 투입한다(사용자: own 4장 가용 → 실패 섞은 run부터). 제약은 공식 트레이너/데이터셋 클래스를 그대로 쓰면서 학습 입력이 기존 base FD 평가 입력과 동일함을 테스트로 보증하는 것.
scripts/robolab_to_lerobot.pylerobot의 writer(프레임마다 PNG → 나중 인코딩, 8M 파일)를 버리고 PyAV로 4패널 mp4 스트리밍 디코드 → 3패널 crop → per-view h264(crf 23, GOP 8, bf 0) 직접 인코딩; parquet/meta는 DROIDLeRobotDataset이 읽는 컬럼만 정확히 씀. 패널 순서 [head|left|right|wrist] 80/80 확인. cartesian_position = FK(achieved joints)→xyz+euler_xyz. episode_id 컬럼으로 keep-ranges 키를 프레임워크 패치 없이 맞춤. 재개 가능(marker)·샤딩·finalize.
cfgon_FruitsMovingOrangeOrLimeTask_run0_env1, cfgon_FruitsOnPlateTask_run0_env1, cfgoff_FruitsMovingOrangeOrLimeTask_run0_env3)에 NaN 수천 개 → scipy SVD/lstsq가 SVD did not converge로 죽던 원인. 인덱스에 skip_reason 플래그(번호 유지), 모든 소비자가 제외. 재수집 파이프라인에도 같은 게이트 필요.scripts/cosmos3_env.shfd_replay 프리앰블 공용화 + torchcodec shim: PyAV가 ffmpeg 8 libs를 mangled 이름으로 번들해 torchcodec이 libavutil.so.60을 못 찾음 → .venv/ffmpeg_shim/ 심볼릭 링크. lerobot decode_video_frames(torchcodec 기본)가 학습 로더에서 쓰이므로 필수.
| 세트 | ep | 성공/실패 | 프레임 | 태스크 |
|---|---|---|---|---|
| test-A (seen task / unseen ep) | 52 | 11/41 | 58,620 | 26 |
| test-B (unseen task) | 259 | 45/214 | 353,719 | 15 |
| val | 79 | 10/69 | 115,814 | 54 |
| train | 1,513 | 195/1,318 | 2,130,583 | 105 |
test-B: BlockStackingOrderAgnostic, BlocksInBin, BowlStackingLeftOnRight, ButterAboveRaisin, CondimentsInBin, DishesInBin, ElectronicsInBin, FruitsMovingOrangeOrLime, PickUpBluePitcher, PutTwoMugsOnShelf, RubiksCubeBehindBowl, Stack3RubiksCube, StackYellowOnRed, ThrowAwaySnacks, WhiteMugInCenterOfTable. 첫 시도에서 코호트 태스크를 제외하니 쌓기가 0개라 규칙 수정(코호트 태스크 허용, 해당 코호트 ep는 test-A→test-B). 라벨은 fd_replay_modes.gather()를 8 run dir 전체(976 ep)에 돌려 확보.
keep-ranges: 공식 use_filter_dict로 split + 사건 가중 동시 구현. 사건 = 첫 close 이후 gripper 전이 + contact detector, ±2 s. 실패 train 1,317 중 1,285 ep에 사건, 중앙값 18/ep(grip 28,606 / contact 4,843), 사건 윈도우 886,089 = 44%.
scripts/test_wm_dataset_parity.py| 검사 | 기준 | 실데이터 8샘플 |
|---|---|---|
| action (dataset 경로 vs fd_replay_prep FK 경로, quantile 후) | max|Δ| < 1e-3 | 7.7e-5 – 1.6e-4 |
| video (concat_view → 736×544 pad, aug off) | mean|Δ| < 4/255 | 2.1 – 3.5 /255 |
prompt (학습 JSON vs inference.action._format_prompt) | 문자열 동일 | 8/8 동일 |
| 스모크 | 결과 | 해석 |
|---|---|---|
| 87812 (own 4 GPU, 4-ep smoke 데이터, 30 iter) | iter 1–24 진행(loss 1.0–1.6), 40 s/iter(3회 중 1회만 4.5 s), GPU util ~10%, GPU당 55–63 GB; iter 25에서 hang → 30분 후 NCCL watchdog(ALLGATHER timeout) → SIGABRT | 데이터로더 병목 + worker 데드락 |
ColorJitter(b/c/s/hue)의 hue(RGB↔HSV)가 51프레임 float 텐서에서 1스레드 5.1 s (no-hue 0.94 s, crop+resize 0.26 s). worker당 ~6 s/샘플 × batch 8 = 48 s, 6 worker → 1 sample/s/rank → 32 samples/step ≈ 32 s + 연산 4.5 s ≈ 40 s — 관측과 일치. 디코드는 17프레임 0.07 s로 무관.OMP_NUM_THREADS=4로 OpenMP 풀을 만든 뒤 worker fork → GNU OpenMP 비 fork-safe → worker 데드락 → 그 rank가 collective에 못 들어감.augment="bc"(crop+resize+brightness/contrast): 단일 프로세스 1.40 s/샘플, fork 8 worker 8.96 samples/s → 10 worker면 32 samples/step ≈ 3 s < 연산 4.5 s → GPU-bound 예상 ~5 s/iter. OMP_NUM_THREADS=MKL=OPENBLAS=1, worker 10, -c 48. spawn은 벤치에서 10분+ 멈춰(대용량 pickling) 불채택.스모크 2차(87867, extra, 실데이터)는 클러스터 119/120으로 대기 중. 본 run 87870(own)은 사용자 own 쿼터(mot_v1b 4 + ev_mid10k 2 + longmem_real 1 GPU, mem 1.43/1.8 TB)가 비면 자동 시작 — 사용자 결정 "own 대기".
인터페이스 동일성을 테스트로 고정했으므로 base vs FT의 차이는 데이터에만 귀속된다. 쿡북과 vendored 프레임워크 사이의 불일치(format_prompt_as_json 미전달, TOML 금지 키)와 로더 함정(hue aug, fork/OMP, rank 양자화 혼합비, torchcodec shim)은 전부 우리 쪽에서 흡수했고 memory/context에 기록했다. 데이터 품질 게이트(NaN trace)는 재수집 때도 필요하다.
scripts/export_fd_ckpt.sh로 스모크 ckpt export → fd_replay 2 ep 경로 검증RoboLab/robolab/eval/episode.py:run_episode의 env.step() 루프(157행)상세: claude/260820/progress-wm_ft_phase0.md · 체크리스트 claude/plan.md