Index
2026-05-14 — Analysis

Segments-aware adapter sanity — 전체 프로세스 + 결과

memer | dusting ckpt × HF subtasks.json (11 segments) on combo_002_L29_S48_0006 · VLA-less probe

TL;DR

303.7s
wall-clock
312
total calls
11
segments (6 PnP + 5 transit)
82.5%
memory_build "shelf" %
1/3
keyframe fingerprint diversity
0/3
fixture noun hit (final)

1실험 setup — 입력으로 들어간 것

Video
10230 frames @ 20fps (~8.5분)
Cameras
agentview L+R (320×180)
Stride
100 frames → 103 calls
Model
dusting Qwen3-VL-4B
Memory
8-frame FIFO (1D cluster merge)
Tests
3 (steak / bowl / fish)

combo_002 segments (HF subtasks.json — 11개)

frame rangespantask_nametypeinstruction (요약)
[0, 724)724MoveFridgeToFreezerPnPsteak: fridge → freezer
[724, 1003)279Transittransit→ cabinet
[1003, 2470)1467RestockBowlsPnPbowls: counter → cabinet
[2470, 2680)210Transittransit→ oven
[2680, 3406)726OvenBroilFishPnPfish: bottom rack of oven
[3406, 3617)211Transittransit→ stove
[3617, 4846)1229SimmeringSaucenon-PnPpan + tomato/onion + burner
[4846, 5038)192Transittransit→ cabinet
[5038, 7512)2474ArrangeUtensilsByTypenon-PnPwooden + metallic 분리
[7512, 7796)284Transittransit→ sink
[7796, 10230)2434ClearSinknon-PnPonion/tangerine 빼고 bowl/cup 채우기

2한 번의 MemER 호출이 뭘 하는가

매 stride 호출(=1 step)마다 다음이 일어남:

📥 INPUT
• 직전 100 frame chunk (2 camera × 100 = 200 image)
instruction string ← 이 step에 줄 자연어 지시 (핵심 변수)
• 누적된 EpisodicMemory state (FIFO 8개 keyframe)
⚙️ INTERNAL — VLM 처리
(a) 이 chunk에서 어떤 frame을 keyframe으로 메모리에 추가할지 결정 (1D clustering)
(b) 메모리 + 이번 chunk를 종합해서 "지금 해야 할 subtask" 한 줄 생성
📤 OUTPUT
predicted_subtask — 예: "place the steak on the bottom shelf"
memory_indices_after — 이 step 끝나고 메모리에 남은 frame 번호들
핵심: MemER는 stateful하다. 매 step마다 메모리가 갱신되고, 다음 step은 그 메모리를 보고 새 결정을 함. 따라서 같은 video라도 instruction이 다르면 → 다른 keyframe이 메모리에 들어가야 → 다른 subtask가 출력되어야 (가설상).

3Baseline vs Segments — instruction을 어떻게 다르게 줬는가

BASELINE (기존)

모든 103 step에 같은 instruction = test query 한 줄.

step 0 (frame 0): "Show me where the steak is placed."
step 1 (frame 100): "Show me where the steak is placed."
step 2 (frame 200): "Show me where the steak is placed."
⋮ (100 step 더)
step 102 (frame 10200): "Show me where the steak is placed."

Final answer = step 102의 출력

→ 총 103 calls × 3 tests = 309 calls

SEGMENTS (신규)

step별 instruction이 frame 위치에 따라 segments JSON에서 lookup.

step 0 (frame 0): "There's a steak in the fridge that needs to be moved..."
step ~8 (frame 800): "Approach the cabinet for the next task."
step ~15 (frame 1500): "Open the cabinet. Pick the bowls..."
⋮ (segments 따라 변동)
step 102 (frame 10200): "Remove the onion and tangerine from the sink..."
step 103 (final query): "Show me where the steak is placed." ← test query

Final answer = final_query phase의 출력

→ 총 104 calls × 3 tests = 312 calls

왜 이게 "더 옳은" 설정인가: scene-mem-benchmark는 long-horizon 시나리오에서 "사전에 본 것을 기억해서 마지막 query 답하기"를 측정함. Baseline은 처음부터 query를 보여주니 모델이 query에 anchored 될 수 있음 — 진짜 memory test가 아님. Segments는 "수행 중"인 상태로 메모리를 쌓고 마지막에만 query를 던지는 시나리오라서 MemER online deploy 디자인에 정합.

43개 측정 항목 — 정확한 계산법 + 의미

AVocab leakage — "shelf"가 들어간 step 비율

for each test: rows = predictions.jsonl if segments: target_rows = [r for r in rows if r["phase"] == "memory_build"] # 103개 else: target_rows = rows # 103개 shelf_count = sum(1 for r in target_rows if "shelf" in r["predicted_subtask"].lower()) ratio = shelf_count / len(target_rows)

의미: Segments에선 instruction에 "freezer/cabinet/oven" 단어를 명시. 모델이 instruction을 따른다면 → 출력에 "shelf"가 거의 안 나와야 함. 82.5% step에서 여전히 "shelf" → 모델이 instruction 무시하고 학습된 vocab으로 끌려감.

BKeyframe diversity — 마지막 메모리 상태가 test별로 다른가

fingerprints = set() for each test: last_row = predictions.jsonl의 마지막 row (segments: phase=="final_query" row, baseline: step 102) mem_indices = last_row["memory_indices_after"] # 예: [669, 1399, 3189, 3599] fingerprints.add(tuple(sorted(mem_indices))) diversity = len(fingerprints) # 3 tests니까 max 3

의미: 같은 video라도 query("steak 어디?" vs "bowl 어디?")가 다르면 모델이 다른 frame을 keyframe으로 골라야 정상 (instruction-aware). 3 = ideal (test별 다른 메모리) / 1 = collapse (query 영향 0).

CFixture noun — final answer가 GT fixture를 언급하는가

for each test: final_text = (segments: phase=="final_query"의 row, baseline: last row).predicted_subtask fixture_type = eval_spec의 GT # test_00=freezer, test_01=cabinet, test_02=oven hit = (fixture_type in final_text.lower())

의미: 이 benchmark의 핵심 평가 — "물체가 어디 놓였는지 모델이 알고 있는가". GT는 freezer/cabinet/oven인데 모델은 "shelf"라고만 답함. 0/3 = fixture noun 한 번도 안 나옴.

한계 명시: 이번 sanity는 VLA를 안 돌렸음. 진짜 robot이 fridge로 가서 fish를 freezer에 넣었는지(=memory_success: R<1.2m AND door joint ≥ 0.5)는 측정 안 함 — 그건 Pi0.5 통합 후. 이번 sanity는 MemER text output 자체의 품질(메모리 / 어휘 / instruction-following)만 본 사전 검증.

5결과 요약 — 3 항목 한눈에

5.1 Vocab leakage (memory_build phase)

testbaselinesegmentsΔ판정
MoveFridgeToFreezer (steak)93.2%82.5%-10.7%p미미 개선
RestockBowls (bowl)91.3%82.5%-8.8%p미미 개선
OvenBroilFish (fish)94.2%82.5%-11.7%p미미 개선

5.2 Keyframe diversity (3 test 사이 final memory fingerprint)

modetest_00 (steak)test_01 (bowl)test_02 (fish)unique
baseline(669, 1129, 1929, 3599)(669, 1229, 1929, 2879, 4639)(669, 1229, 1929, 3599)3
segments(669, 1399, 3189, 3599)(669, 1399, 3189, 3599)(669, 1399, 3189, 3599)1 (collapse)

왜 segments가 오히려 collapse를 만들었나 (가설)

dusting LoRA는 keyframe scoring head도 "shelf-pattern instruction" 분포에서 학습됨. Segments에서 action-form instruction이 step마다 들어가면 그 instruction에 더 강하게 anchored 되어 → 같은 segment에선 같은 keyframe이 픽됨 → 3 query 모두 같은 segment trajectory를 따라가 → final memory 동일 수렴. 반면 baseline은 query (test별 다름)가 micro-noise를 만들어 fingerprint가 갈림.

5.3 Fixture noun in final answer

targetGT fixturebaseline finalsegments finalhit?
steakfreezerplace the steak on the bottom shelfplace the steak on the bottom shelf✗ ✗
bowlcabinetplace the red bowl on the top shelfplace the red plate on the top shelf✗ ✗ +회귀
fishovenplace the fish on the bottom shelfplace the fish on the bottom shelf✗ ✗

6의미 (Takeaway)

1. Prompt strategy로는 vocab lock-in을 못 푼다 — 모델 fine-tune 외 길 없음
Best-case prompting (정확한 phase timing + action-form sub-instruction)에도 80%+ "shelf" 유지, fixture noun 0/3. 이미 학습된 vocab 분포가 너무 강해 prompt로 누를 수 없음.
2. Counter-intuitive: segments가 keyframe diversity를 오히려 collapse
Net으로 segments가 baseline보다 손해 (vocab은 -10%p 미세 개선이지만 keyframe 1 ← 3 회귀, fixture noun 0/3 동일). dusting LoRA의 keyframe scoring 자체가 instruction-anchored.
3. Eval semantic은 옳음, adapter도 잘 동작
validate / find_segment / final_query phase 모두 plug-and-play. LoRA V2 ckpt 받으면 즉시 동일 명령어로 재현 가능 — --model-path만 교체하면 끝.

7다음 (Next)

  1. LoRA V2 sanity — 같은 명령어, --model-path만 LoRA path로. Ablation matrix 4가지 완성:
    모델baseline (query 전체)segments (action-form)
    dusting✅ 260513✅ 이번
    LoRA V2
    → vocab/keyframe 효과를 모델 vs prompting으로 isolated 측정 가능
  2. Recent-frame anchoring 점검 — 모든 final memory의 max index가 ~3599 (전체 10230 중 35% 지점). recent_frames_length=8이면 video 마지막 8 step은 무조건 들어가야 정상 — 별도 점검 필요.
  3. 858 scenario 전체 timing 활용 — combo_002 외 다른 scenario도 로컬 다운로드 후 같은 sanity 반복 가능. 단, 결론(vocab은 모델-bound)은 이미 명확하므로 LoRA V2 검증 끝난 뒤로 미룸.