Index
2026-05-13 — Experiment

MemER (dusting ckpt) probe on Keh0t0/scene-mem-benchmark

memer | combo_002_L29_S48_0006 (RoboCasa kitchen, 3-test scenario) · VLA-less inference probe

TL;DR

100%
parse OK
309
total calls
275.6s
runtime (3 tests)
3/3
objects recognized
0/3
fixture nouns used
4–5
kf events / 103 calls

1 배경 / 목적

Keh0t0/scene-mem-benchmark는 long-horizon scene memory를 측정하는 RoboCasa 기반 벤치마크. 핵심 컨셉:

Policy가 prior-task 비디오 3개를 보고 "어디에 뭐가 놓였는지" 기억해 둔 다음, 새 instruction ("Show me where the steak is placed.")에 대해 mobile base를 그 fixture까지 끌고 가서 문을 열 수 있는가.

오늘 목표: MemER의 inference-only probe — prior 비디오를 흘려넣고 test instruction에 대해 (a) 어떤 keyframe을 메모리에 넣는지, (b) 어떤 subtask 문자열을 뱉는지 정성 관찰. Pi0.5 통합 + 정량 평가는 다음 세션으로 미룸.

왜 inference-only? 벤치마크는 VLA-level이라 mobile-base action vector를 emit해야 함. MemER 공개 release에는 high-level subtask emitter만 있어서 memory_success 측정 불가. low-level VLA 통합 전에 MemER 출력의 적합성을 먼저 봐야 함.

2 작업 내용

2.1 Dataset schema (4204 files / 858 scenarios)

Keh0t0/scene-mem-benchmark/ (private, owner 토큰으로만 접근) ├── eval/ (벤치마크 인프라) │ ├── base_policy.py # BasePolicy: reset(instr, video_paths) + get_action(env) │ ├── eval_runner.py # robosuite/robocasa env 로드 + 1500-step rollout │ └── success_fn.py # memory_success = approached_fixture(R<1.2m) ∧ door_open(j≥0.5) └── data/<combo_XXX_LXX_SXX_NNNN>/ (858 scenarios across 34 combo prefixes) ├── eval_spec.json # max_steps=1500, video_files, env_files, tests[] ├── env/ │ ├── unified_model.xml # ~1MB mujoco scene │ ├── env_args.json # PandaOmron + HYBRID_MOBILE_BASE controller │ ├── ep_meta.json # object_cfgs, fixtures(50+), cam_configs, lang │ └── start_state.npy # post-prior-task sim state └── videos/ ├── robot0_agentview_left.mp4 # 256×256 @ 20 fps, ~10000 frames ├── robot0_agentview_right.mp4 └── robot0_eye_in_hand.mp4

2.2 Eval contract

# base_policy.py (29 lines) class BasePolicy: def reset(self, instruction: str, video_paths: Sequence[str]) -> None: ... def get_action(self, env) -> np.ndarray: ... # success_fn.py memory_success = approached_fixture(robot_base_xy, target, radius=1.2m) AND door_open(any joint ≥ 0.5)

→ 객체 잡기/조작은 평가 안 함. "기억하고 있던 fixture로 mobile base를 끌고 가서 문 열기"만 본다.

2.3 MemER mismatch 표

측면scene-mem-benchmark 요구MemER 공개 코드
출력np.ndarray action (PandaOmron HYBRID_MOBILE_BASE: arm OSC_POSE 6 + gripper 1 + base velocity 3 + torso 1 ≈ 11)current_subtask 문자열
메모리정책이 알아서 (LSTM/attention/whatever)EpisodicMemory: VLM keyframe 1D clustering FIFO
판정mujoco state (body_xpos, qpos)문자열 vs GT subtask 매칭

2.4 어댑터 작성

scripts/eval_scene_mem_one_scenario.py (171 lines) — 한 scenario 안의 모든 test sweep, model 1회 로드. 카메라는 agentview_left + agentview_right 2장 vertical stack (eye_in_hand 제외 — wrist 뷰는 해석 어려움).

CUDA_VISIBLE_DEVICES=0 timeout 1800 \ /home/.../conda_envs/envs/memer/bin/python \ scripts/eval_scene_mem_one_scenario.py \ --scenario-dir ~/Dataset/scene-mem-benchmark/data/combo_002_L29_S48_0006 \ --model-path ~/ckpts/memer-dusting-qwen3vl-4b-step-1500 \ --output-dir eval_outputs/scene_mem_combo_002_ep0006 \ --stride 100 --attn-implementation sdpa --save-raw-text

3 결과

combo_002_L29_S48_0006 (Layout 29, Style 48 RoboCasa kitchen) — 3 tests × 103 calls = 309 inference, 275.6s wall clock. parse 100%.

3.1 Subtask 분포 — top-5 per test

TestInstructionTop subtask (count / 103)2ndTarget objectTarget fixture
0"Show me where the steak is placed."place the steak on the bottom shelf (64)pick up spatula (6)steak ✅freezer ❌
1"Show me where the bowl is placed."place the red bowl on the top shelf (54)place the bowl on the bottom shelf (9)bowl ✅cabinet ❌
2"Show me where the fish is placed."place the fish on the bottom shelf (56)place the red bowl on the top shelf (13)fish ✅oven ❌
Object recognition 살아있음: dusting checkpoint가 학습한 적 없는 어휘인데도 3개 target object 모두 정확히 명명. SFT가 LLM head + 프롬프트 contract만 바꾸고 vision/MLP frozen이었던 게 (tune_mm_vision=False, tune_mm_mlp=False) 효과를 봄.
Vocabulary는 dusting에 lock-in: 출력 패턴이 "place X on top/bottom shelf"로 고정. RoboCasa fixture 명사 (freezer/oven/cabinet)나 mobile-base 어휘 (navigate to / approach) 0회. 심지어 test 1에서 "put down duster"까지 누수.

3.2 Memory FIFO 진화 — 3 query 비교

TestMemory progression (raw frame index, 20 fps)Final memorykf events / 103 calls
0 (steak)[] → [669] → [669,1129] → [669,1129,1929] → [669,1129,1929,3599][669, 1129, 1929, 3599]4
1 (bowl)[] → [669] → [669,1229] → [669,1229,1929] → [669,1229,1929,2879] → [+4639][669, 1229, 1929, 2879, 4639]5
2 (fish)[] → [669] → [669,1229] → [669,1229,1929] → [669,1229,1929,3599][669, 1229, 1929, 3599]4
Keyframe selection은 instruction-blind: 3 query 모두 ts=699에서 frame 669 픽 (subtask "close top shelf"), ts=1999에서 frame 1929 픽. 즉 같은 prior 비디오를 어떤 instruction으로 보든 거의 같은 frame을 메모리에 넣음. instruction-conditioned keyframe selection은 안 작동.

3.3 모든 test에 공통으로 들어간 keyframe 시각화

keyframe 669
Frame 669 (~33s) — 3 query 모두에서 첫 메모리 (subtask "close top shelf")
keyframe 1129
Frame 1129 (~56s) — test 0(steak) 메모리
keyframe 1929
Frame 1929 (~96s) — 3 query 공통 메모리
keyframe 3599
Frame 3599 (~3분) — test 0,2 메모리
keyframe 4639
Frame 4639 (~3.9분) — test 1(bowl) 마지막 메모리

3.4 Raw text 샘플 (test 0)

ts= 199 {"current_subtask": "take blue block off top shelf", "keyframe_positions": []} ts= 699 {"current_subtask": "close top shelf", "keyframe_positions": [5]} ← 5번째 context 프레임 = abs frame 669 ts= 1199 {"current_subtask": "place the red plate on the top shelf", "keyframe_positions": [1]} ts= 1599 {"current_subtask": "pick up spatula", "keyframe_positions": []} ts= 1999 {"current_subtask": "place the red bowl on the top shelf", "keyframe_positions": [1]} ts= 6099 {"current_subtask": "place the steak on the bottom shelf", "keyframe_positions": []} ts=10229 {"current_subtask": "place the steak on the bottom shelf", "keyframe_positions": []}
Keyframe 픽은 매우 보수적: 103 call 중 4–5건만 keyframe_positions non-empty. 나머지 99% call은 빈 리스트 반환 → 시각적 saliency가 강한 순간만 골라 넣음. instruction과의 연관성은 약함.

4 Takeaway

1. Object recognition은 살아있다 ✅

3 query 전부 target object("steak"/"bowl"/"fish")를 정확히 명명 — base Qwen3-VL-4B-Instruct의 visual+language 능력이 dusting finetune 후에도 보존됨. SFT가 LLM head + prompt contract만 바꾸고 vision/MLP는 frozen이었던 게 효과를 봄.

2. Vocabulary는 dusting에 박혀있다 ❌

출력 패턴이 "place X on top/bottom shelf"로 고정. RoboCasa의 적절한 fixture 명사 (freezer/oven/cabinet)나 mobile base 어휘 (navigate to/approach)는 절대 안 나옴.

→ Pi0.5와 cascade 시 conditioning이 망가짐: Pi0.5-RoboCasa는 "approach the freezer" 같은 navigation 명령을 받기를 기대할 텐데 MemER는 "place the steak on the bottom shelf"만 줌. 이대로 붙이면 score 0% 가능성.

3. Keyframe selection은 instruction-blind

3 query 모두 frame 669/1929를 메모리에 동일하게 픽. 시각적 saliency는 잘 잡지만 instruction-conditioning은 약함. scene-mem-benchmark의 본질 task ("이 query에 대한 답이 어느 frame에 있는가")에는 부적합.

이 약점은 메모리 메커니즘 자체보다 dusting finetune의 single-task vocabulary lock-in의 부산물로 보임. RoboCasa-tuned MemER에서는 query별로 다른 frame을 뽑을 가능성.

5 Next Steps

1순위 — Prompt-level vocabulary enforcement (다음 세션)

MemER prompt를 수정해서 RoboCasa primitive 리스트 중 하나만 고르게 강제:

Output JSON with: - current_subtask: ONE OF [navigate_to_<fixture>, open_<fixture>, close_<fixture>, ...] - keyframe_positions: ...

memer_eval/contract.pyDEFAULT_SYSTEM_PROMPT 변경만으로 코드 수정 최소. dusting-tuned LLM이 이 enum을 얼마나 신뢰성 있게 따를지 미지수 — 5–10 scenarios sanity-check 필요.

2순위 — Pi0.5-RoboCasa 통합

사용자 확정: Pi0.5는 robocasa 학습된 게 있고 robosuite+robocasa 환경도 이미 setup. 다음 세션에서:

  • Pi0.5 ckpt 위치 + load API 확인 (사용자에게 받아야 함)
  • 통합 어댑터: MemerPi05Policy(BasePolicy) — reset에서 prior 비디오를 MemER에 흘려넣어 메모리 채우고, get_action에서 매 step마다 MemER subtask + Pi0.5 act
  • 비용 분석: 257 scenario × ~80s memory build = ~17h sequential. 첫 세팅은 sample subset (combo_002 27개 등)
  • GPU placement: MemER 9GB + Pi0.5 ~8GB → 1 B200(180GB)에 둘 다 OK

스케일링 — MemER 부분만 257 scenario 전체 sweep

scripts/eval_scene_mem_all.py batch wrapper로 확장. 257 scenario × ~3 test = ~771 inference batch (각 100 call). 총 ~14h sequential at 80s/test → SLURM 1 GPU job (sbm "bash scripts/scene_mem_all.sh" --gres=gpu:1 -c 8 --mem 200GB --qos=extra). 결과 요약: scenario별 keyframe 위치 분포, top subtask 일치도, vocabulary leakage rate.

Ablation 후보

  • eye_in_hand 카메라 활용: 지금 agentview L+R만 stack. wrist 단독 또는 left+wrist 조합으로 ablation
  • Stride/subsample sensitivity: stride=50 (2× cost)에서 keyframe 선택이 더 dense해지는지 — 1 scenario에서 측정