~/Dataset/robomme/)을 입력으로 쓰고 싶은데, 두 가지 mismatch 존재:
1. RoboMME = LeRobot v2.0 (meta/episodes.jsonl + meta/tasks.jsonl) / MemER = v3 (meta/subtasks.parquet 요구) — evaluate_rollout() 직접 사용 불가.
2. RoboMME는 subtask GT가 아예 없음 (annotation.language.language_instruction{,_2,_3} 셋 다 에피소드 task 프롬프트 복사본, 프레임 내내 불변).MemERDeploymentPolicy만 직접 구동 → predictions.jsonl 덤프. accuracy는 GT 없어서 계산 불가, 무시./home/nas_main/taewoongkang/conda_envs/envs/memer/ (python 3.11).
설치 실측 버전 (2026-04-24):
torch 2.11.0+cu130 # accelerate가 transitive로 pull
torchvision 0.26.0+cu130 # qwen_vl_utils가 import
transformers 5.6.2 # pyproject 요구 >=4.57
qwen-vl-utils 0.0.14
pyarrow 24.0.0
opencv-python-headless 4.13.0
numpy 2.2.6 / Pillow 12.2 / tqdm 4.67.3
huggingface_hub 1.12.0 # `huggingface-cli` deprecated, `hf` 쓰세요
lerobot 일부러 설치 안 함: v2.0 포맷이라 LeRobotDatasetMetadata 쓸 수 없고, 어차피 MemERDeploymentPolicy는 lerobot을 top-level로 import 안 함.
pip install -e memer/ --no-deps로 memer_eval 패키지 import 경로 확보.
scripts/eval_robomme_subtask.py:
- meta/episodes.jsonl에서 에피소드 task 문자열 추출
- 각 카메라의 videos/chunk-XXX/<key>/episode_YYYYYY.mp4를 cv2로 디코드 (RGB uint8)
- MemERDeploymentPolicy(camera_keys=[wrist_image_left, exterior_image_1_left]) 생성
- 매 stride 프레임마다 policy.step(*chunk) 호출 (buffer는 다 쌓이고 inference는 chunk의 마지막 프레임에서만)
- predictions.jsonl + run_info.json 덤프
카메라 키 이름 주의: RoboMME는 observation.images.wrist_image_left / exterior_image_1_left (MemER 기본의 wrist_left / exterior_1_left 가 아님).
HF: ajaysri/memer-dusting-qwen3vl-4b-step-1500
Local: /home/nas_main/taewoongkang/ckpts/memer-dusting-qwen3vl-4b-step-1500/
Total: 24G (model safetensors ~8.5G + optimizer/scheduler/rng_state 나머지)
Arch: Qwen3VLForConditionalGeneration, bfloat16, 36 layers, 2560 hidden
B200 login node, GPU 1 (비어있음). Attention은 sdpa override — flash-attn 미설치 상태라 auto-select는 flash_attention_2 찍어서 ImportError. sdpa가 기본 fallback으로 적합.
CUDA_VISIBLE_DEVICES=1 timeout 1800 \
/home/nas_main/taewoongkang/conda_envs/envs/memer/bin/python \
scripts/eval_robomme_subtask.py \
--lerobot-path ~/Dataset/robomme/BinFill_lerobot \
--episode-index 0 \
--model-path ~/ckpts/memer-dusting-qwen3vl-4b-step-1500 \
--output-dir eval_outputs/robomme_binfill_ep0 \
--stride 5 --attn-implementation sdpa --save-raw-text
BinFill ep0 (550 frames, 10fps, stride=5 → 110 inference calls)
| Count | Predicted subtask |
|---|---|
| 60 | place the red block on the top shelf |
| 18 | place the red block on the bottom shelf |
| 14 | press the top button |
| 10 | press the button |
| 3 | take red block off bottom shelf |
| 2 | pick up red block |
| 2 | reset gripper |
| 1 | press the top-right button |
| 프레임 구간 | 실제 로봇 행동 (mp4 기준) | 모델 예측 주요 primitive |
|---|---|---|
| 0 – 15 | 초기 배치/접근 | take red block off bottom shelf (x3) |
| 19 – 254 | 첫 빨간 큐브 bin으로 이동 + 두 번째 큐브 | place the red block on the bottom shelf (x18), pick up red block (x2) |
| 69 – 549 (도배) | (전반적 ambient fallback) | place the red block on the top shelf (x60) |
| 219 – 534 | 버튼 press 구간 | press the top button (x14), press the button (x10), reset gripper (x2) |
ts= 19 → picked frame 4
ts= 34 → picked frame 4
ts= 69 → picked frame 34
ts=114 → picked frame 79
ts=139 → picked frame 124
ts=149 → picked frame 149
ts=154 → picked frame 144
ts=159 → picked frame 144
ts=169 → picked frame 144
ts=174 → picked frame 139
ts=179 → picked frame 164
ts=299 → picked frame 264
메모리 최종 상태 (1D clustering merge_distance=5 subsampled = 25 raw frames 적용 후):
Final mem: [4, 34, 79, 144, 264]
All candidates seen: [4, 4, 34, 79, 124, 139, 144, 144, 144, 149, 164, 264]
→ 인접 keyframe들 {139, 144, 149}가 144로 클러스터 병합, {4, 4}가 4로 중복 제거 → 최종 5개.
predicted_subtask가 VLA에 넘어갈 전부. embedding/hidden state 공유 없음. 스크립트의 predictions.jsonl 한 줄이 곧 VLA 한 스텝의 입력 명세.press the top button 류가 버튼 press 구간(ts=219-534) 에만 집중적으로 나타남 — 실제 BinFill 스크립트 후반과 일치
- subtask vocabulary는 학습 분포에 강하게 박혀있음: "shelf" 라는 단어가 BinFill에 없는데도 "top shelf / bottom shelf"가 80% 이상의 step에서 나옴 → dusting의 공간 primitive 재사용Fine-tuning 없이 RoboMME 정량 평가 불가: subtask GT 자체가 없고 vocabulary도 dusting vs BinFill 사이 공집합 → accuracy 계산하려면 - RoboMME에 subtask 라벨을 직접 달아야 하거나 - Qwen3-VL-4B-Instruct base 모델로 zero-shot (dusting-tuned 대신) - 또는 RoboMME에서 직접 finetune (scripts/generate_sft_data.py로 SFT data 만들고 QwenLM/Qwen3-VL repo로 학습, README.md §9 참조)
다른 RoboMME task 실험: BinFill은 pick+place+press 세 phase 혼재. 더 clean한 single-primitive task (PickXtimes_lerobot, StopCube_lerobot)에서는 subtask sequence가 더 간결할 가능성. 어댑터 이미 준비돼있으니 --lerobot-path만 바꿔 바로 비교 가능.
Keyframe prompt 영향도 실험: --memory-length, --merge-distance, --recent-frames-length 변화시 VLM 출력 일관성이 어떻게 바뀌는지. 지금 default (8/5/8) 고정 값.
VLA 붙이기: openpi(README §5 추천)로 Franka/DROID VLA 로드 → predicted_subtask 을 language instruction으로 주입 → closed-loop. 이건 별도 프로젝트 규모.
Flash-attn 설치 여부: 현재 sdpa 0.78s/call (B200 1 GPU). flash_attention_2 설치하면 ~2-3x 가속 예상. /etc/claude-code/CLAUDE.md §11 Path A로 /usr/local/cuda-13.0 export 후 flash-attn 빌드. 현재는 불필요 수준의 속도.
| 경로 | 내용 |
|---|---|
scripts/eval_robomme_subtask.py |
RoboMME v2 → MemER deploy 어댑터 CLI |
claude/RUNNING_ON_ROBOMME.md |
경로/명령어 캐노니컬 레퍼런스 (다른 세션/사람이 바로 따라갈 수 있음) |
eval_outputs/robomme_binfill_ep0/predictions.jsonl |
110 스텝 prediction 원본 |
eval_outputs/robomme_binfill_ep0/run_info.json |
config/duration/camera/platform 메타 |
eval_outputs/robomme_binfill_ep0_smoke/ |
stride=100 smoke test 결과 (ablation용 보관) |