Index
2026-09-07 — Progress

RoboTwin 43-seen post-training 셋업 및 학습 제출

lingbot-va | job 112772 · 8 GPU core-own · 32,000 step · ETA ~19 h

TL;DR

43
task
2,150
episode
32,000
step
2.16
s/it (8 GPU)
30 GB
데이터
0
hold-out 누수

1 배경 / 목적

Zero-WAM 43/7 split 조사에서 확정한 프로토콜에 따라, LingBot-VA를 43 seen task(clean 50)로만 post-train 하는 파이프라인을 배선하고 제출했다. 목표 앵커는 논문의 LingBot-VA baseline unseen 7 평균 17.45%.

핵심 제약: hold-out 7개 task가 어떤 경로로도 학습에 들어가면 실험이 무효다.

2 작업 내용

2.1 누수 방지 — "받지 않는다"를 1차 방어선으로

lerobot_latent_dataset.py:39-51의 construct_lerobot_multi_processor는 dataset_path를 재귀 walk 하며 모든 meta/info.json을 찾는다. 즉 디렉토리에 존재하면 무조건 학습에 들어간다. 따라서 필터링이 아니라 애초에 7개를 받지 않는 쪽을 택했다.

층위치검사
1디스크7개 task 디렉토리가 아예 없음
2va_robotwin_seen43_train_cfg.py import 시dataset_path 하위에 hold-out 이름이 있으면 assert 실패
3script/train_robotwin_seen43.sh (GPU 할당 전)43개 정확히 + hold-out 0개 + empty_emb.pt 존재

2.2 데이터 획득 — 세 번 막히고 세 번 원인을 잡음

(a) hf download --include/--exclude: 10분 동안 4.1 MB. --include/--exclude는 repo 전체 파일 목록을 먼저 열거한 뒤 필터링한다. 이 repo에는 lerobot_robotwin_eef_aug_500(50 task × 500 ep)도 있어 dataset info JSON이 10 MB를 넘는다 (/api/datasets/... 조회가 maxContentLength 10485760 exceeded로 실패한 것과 같은 원인). 프로세스 rchar가 20초당 ~1.5 MB씩 증가 — 파일이 아니라 트리 JSON을 계속 읽고 있었다.
→ task 디렉토리별 list_repo_tree(recursive=True) 43회로 교체. 열거 5분 내 완료, 15,260 파일 확인.
(b) 파일별 다운로드: HTTP 429. 익명 한도 1000 API req / 5분인데 파일이 15,260개. 안전 속도로 낮추면 ~2.6시간.
→ git-lfs 배치 API로 전환(요청 수 ~100배 감소).
GIT_LFS_SKIP_SMUDGE=1 git clone --no-checkout --depth 1 <repo> .rt_git # 62 MB git sparse-checkout init --cone && git sparse-checkout set <43 dirs> GIT_LFS_SKIP_SMUDGE=1 git checkout HEAD # 43 dir / 15,259 pointer ✓ git lfs pull # ← 여기서 sparse 무시
(c) git lfs pull이 sparse-checkout을 무시 — 415 GB 다운로드. git checkout 직후에는 정확히 43 dir / 15,259 파일이었으나, git lfs pull(= lfs fetch + lfs checkout)이 sparse 설정을 무시하고 repo 전체(aug_500 + hold-out 7개 포함)를 받아 워킹트리에 펼쳤다. 43개만 mv로 옮기고 .rt_git 전량 삭제 — 결과 데이터는 정상이나 필요량 30 GB 대비 415 GB는 순수 낭비. 다음엔 git lfs pull --include="<paths>"를 명시할 것.

2.3 생성/수정한 파일

파일내용
wan_va/configs/va_robotwin_seen43_cfg.pyROBOTWIN_UNSEEN_TASKS 단일 정의, base 스냅샷 경로(LINGBOT_MODEL_DIR override)
wan_va/configs/va_robotwin_seen43_train_cfg.pynum_steps=32000, save_interval=4000, cfg_prob=0.1, lr 1e-5, batch 1 × accum 1, 누수 assert
wan_va/configs/__init__.pyrobotwin_seen43, robotwin_seen43_train 등록
script/download_robotwin_seen43.py43 task 전용 다운로더 (skip-existing + rate limit)
script/train_robotwin_seen43.sh학습 런처. #SBATCH 없음 → sbmr 제출

train_robotwin_seen43.sh는 FurnitureBench scripts/lingbot/train_lingbot.sh에서 검증된 요소를 이식: WANDB 키를 ~/envs/api_keys.txt에서 비출력 로드, 워커에 CA 인증서가 없어 SSL_CERT_FILE=$(python -m certifi), FlexAttention/Triton 런타임 JIT용 conda gcc(CC/CXX/CPATH), preempt 대비 최신 체크포인트 자동 resume.

3 결과

3.1 데이터 검증 (최종)

task 디렉토리
43 (hold-out 0)
에피소드 합계
2,150
latent 파일
6,444 / 6,450
크기
30 GB
empty_emb.pt
4,195,895 B
에피소드 2,150은 논문의 "2,150 training samples across 43 tasks"와 정확히 일치 — 우리가 역산한 split이 맞다는 독립적 방증. 각 task info.json의 total_episodes=50 / fps=50 / total_videos=150도 43개 전수 통과.
latent 6개 누락은 업스트림 결손. move_can_pot·pick_diverse_bottles·place_bread_skillet·place_container_plate·place_mouse_pad·place_phone_stand 6개가 각각 wrist 카메라 1개 에피소드의 latent가 없다. HF API로 확인한 결과 원본도 149개 — 전송 누락이 아니다. 로더가 해당 세그먼트를 건너뛰므로 2,150 중 6개(0.28%) 드롭.

3.2 공식 latent 기하 = 추론 서버 규약과 일치

카메라비디오latent텐서
cam_high256×32016×209600×48 (30 latent frame / 117 video frame)
cam_left_wrist / cam_right_wrist128×1608×10720×48 (9 / 33)
fps50 → 12 (stride 4). text_emb (512, 4096)도 .pth에 동봉

wan_va_server.py:335-338의 env_type='robotwin_tshape' 분기가 정확히 이 구성이다 — cam_high는 height×width, wrist는 height//2 × width//2로 인코딩하고 좌우 wrist를 width로 붙인 뒤 cam_high 아래에 height로 스택.

로컬 demo_clean이 있는데 왜 받았나

로컬 RoboTwin/data/demo_clean(33 GB)에 같은 에피소드가 이미 있다 — adjust_bottle ep0가 양쪽 다 139 frame. 하지만 그건 RoboTwin hdf5(jpeg 바이트 + joint/ee pose)이고 latent가 없다. LingBot-VA는 픽셀을 전혀 읽지 않으므로, 받은 696 MB/task 중 651 MB(94%)인 latents/가 실제 목적물이다.

직접 뽑을 수도 있지만(process_data.py, 43×50×3 = 6,450 비디오 VAE 인코딩) 기하가 어긋난다: 어댑터 기본값은 --image-size 256 --target-fps 10 = 세 카메라 균일 256 / 10 fps라 위 T-shape(256 + 128/128, 12 fps)를 재현하지 못하고, 추론 서버가 만드는 latent와 모양이 달라진다.

3.3 스모크 (로그인 노드, GPU 1, 20 step)

항목값
결과exit 0, 20/20 step 완주
latent_loss0.21 ~ 0.61
action_loss0.065 ~ 0.27
grad_norm1.06 ~ 7.39
lr warmup1e-6 → 1e-5 (10 step) 정상
속도step 1은 51.97 s(컴파일), 정상 구간 ~0.76 s/it
데이터셋 init43 task, ~1.5 분 (16 worker)

3.4 학습 제출 및 초기 상태

conda activate lingbot-b200 sbmr 10 "bash script/train_robotwin_seen43.sh 8" \ --gres=gpu:8 -c 64 --mem 1600GB --qos=own --time 36:00:00 -J rt_seen43 → job 112772 · core-own · n1 · RUNNING · 누수 가드 통과
항목값
속도2.16 s/it → 32,000 step ETA ~19 h (--time 36:00:00이 덮음)
step 76 losslatent 0.25 / action 0.023 / grad_norm 0.14
체크포인트transformer bf16 safetensors 9.5 GB/개 × 8개 ≈ 76 GB → ~/checkpoints/lingbot_va/robotwin_seen43_train/checkpoints/
wandbdavian-cv/lingbot_va_robotwin
own 쿼터가 비어 있어 preempt 불가 런으로 확보. 동시 실행 중인 furniture 학습(112492)은 core-extra라 own 캡(core 8 GPU)을 잡지 않는다.

4 Takeaway

의미

  • 데이터 준비가 하루치 작업이 아니라 다운로드 한 번으로 끝났다. RoboCasa 트랙을 막던 두 blocker(base 체크포인트 미다운로드 / latent 추출 스크립트 부재)가 RoboTwin에서는 둘 다 해소되어 있었고, 공식 latent가 추론 서버 규약과 픽셀 단위로 맞아 재생성 confound도 없다.
  • 에피소드 수가 논문의 2,150과 정확히 일치 → split 재구성이 맞았다는 독립적 방증.
  • 누수 방지를 "필터링"이 아니라 "존재하지 않게 만들기"로 설계한 것이 핵심. 로더가 재귀 walk 하는 구조라 필터를 한 군데만 빠뜨려도 조용히 샌다.
  • 도구 선택에서 두 번(hf download 열거, git-lfs sparse 무시) 대가를 치렀다. 둘 다 "옵션이 무엇을 필터링하는가"가 아니라 "필터링 전에 무엇을 하는가"가 문제였다.

5 Next Steps

모니터링

sjob 112772 · slurms/rt_seen43_112772.out · wandb davian-cv/lingbot_va_robotwin

평가 배선 (학습과 병행 가능)

  • evaluation/robotwin/eval_polict_client_openpi.py 2곳 패치: robowin_root = Path("/path/to/your/robowin")(L9) → 허브 경로, ./task_config/ → ./env_cfg/task_config/
  • 나머지 의존성은 허브(96c1fea)에 전부 존재: envs/_GLOBAL_CONFIGS.py:11이 이미 신 경로, description/utils/generate_episode_instructions.py, env_cfg/task_config/demo_clean.yml의 eval_instruction: seen
  • hold-out 7 × 100 ep × 3 seed = 2,100 rollout 러너. _eval_step_limit.yml의 task별 limit 편차 큼(open_microwave: 1500)
  • 하네스 sanity: 공식 lingbot-va-posttrain-robotwin로 hold-out 1개 선행 — 그 ckpt는 50 task를 다 봤으므로 높게 나와야 정상. 실험 수치로는 쓰지 않는다

미결정

  • seed 3개 전부 vs 1개 선행
  • 중간 체크포인트(4k/8k/…/32k) 중 어디를 unseen 7로 평가할지 — 과적합 구간 확인용으로 최소 2~3 지점 권장