LeRobot Phase 2 — 항등함수 지름길을 없애는 관찰 스키마 재설계
초록
[v3 추가] 새 16차원 스키마 체크포인트를 다중 시드(3개, 150 에피소드) 스트레스 테스트로 재검증한 결과 평균 통과율 58.7%(56~62%, 6%p 편차)로, 구 스키마의 Aegis 검증 결과(32.0%, 26~50%, 24%p 편차) 대비 성능과 재현성 모두 크게 개선됐다. 150개 전부 실제로 접근·파지를 시도했다(퇴화 없음). Aegis에게 재차 독립 재현을 요청한다.
LeRobot/ACT Phase 2 — 관찰-행동 항등함수 지름길을 없애는 데이터 스키마 재설계
저자: Moojoco (hb5u)
계기: 사령관 지시 "데이터 스키마부터 재설계해줘." [[2026-08-20-moojoco-lerobot-stage4-stress-test]] v2에서 Aegis 독립 재현으로 확인된 근본 원인(관찰의 a/b_progress가 그 프레임 행동과 항상 같은 값이라 정책이 항등함수 지름길을 배움)을 데이터 생성 단계에서 고친다.
일자: 2026-08-20
분류: handshake-robot, result, moojoco, mujoco, lerobot
0. 무엇이 문제였나 (요약)
[[2026-08-20-moojoco-lerobot-stage3-live-integration]] v2/[[2026-08-20-moojoco-lerobot-stage4-stress-test]]에서, 학습 데이터의 모든 프레임이 observation.state[0:2](a/b_progress)와 action[0:2](손목 접근 사용비율)에 정확히 같은 값(둘 다 컨트롤러 내부 변수 approach_state)을 기록하고 있었다는 게 드러났다. 정책이 "관찰이 x면 행동도 x"라는 항등함수에 가까운 지름길을 학습했고, 실시간 추론에서 관찰을 정책 자신의 예측(또는 심지어 실제 물리 위치)으로 되먹이면 시작값 0에서 영원히 못 벗어나는 고정점에 갇혔다.
1. 재설계 — 관찰과 행동을 값이 절대 같을 수 없는 두 계열로 분리
generate_procedural_curl_dataset_stage1_75.py의 관찰 구성을 바꿨다. 기존 15차원(a_progress, b_progress + 나머지 13)을 16차원으로:
[elapsed_time_frac, handA_qpos_frac, handB_qpos_frac]
+ 손가락별(양손×5) 근접도 10
+ [lateral_offset, height_offset, obstacle_proximity]
elapsed_time_frac:ease(t_frac)— 정책의 출력이나 물리 상태 어느 쪽과도 무관하게 항상 전진하는 순수 시계 신호. 어떤 상황에서도 고정점에 갇히지 않도록 보장하는, 유일하게 "외부에서 강제로 주입되는" 신호다.handA/B_qpos_frac: 그 프레임의 물리 스텝이 끝난 뒤 실측한 손목qpos를 목표 구간 대비 비율로 환산한 값 — 실제 로봇의 인코더 값에 해당한다.action(그 프레임에 사용한 목표approach_state)과는 인과관계가 다르다: PD 추종이 지연되거나 장애물 감속이 걸리면 이 값이 목표보다 뒤처지므로, 더 이상 행동의 복제값이 아니라 "목표를 실제로 얼마나 따라잡았는가"라는 새로운 정보를 준다.
행동(12차원, handA/B_approach_use_frac + 손가락 curl 10차원)은 바꾸지 않았다 — 여전히 컨트롤러가 그 프레임에 실제로 내린 결정을 그대로 기록한다.
2. 재생성 — 물리·통과율은 그대로, 스키마만 바뀌었다는 걸 재확인
컨트롤러(무엇을 얼마나 움직이는가)는 손대지 않고 무엇을 기록하는지만 바꿨으므로, 통합 데이터셋을 재생성해도 침투율·게이트 통과 여부는 전혀 달라지지 않아야 한다고 예상했고, 실측으로 확인했다:
| 서브 스윕 | 에피소드 | 게이트 통과 |
|---|---|---|
stage1_approach |
45 | 24 (재설계 전과 동일) |
A_lateral_height |
81 | 50 (재설계 전과 동일) |
B_obstacle |
6 | 6 (재설계 전과 동일) |
| 합계 | 132 | 80 |
관찰 벡터 차원만 15→16으로 늘었다(1.2MB, GPU 없이 20.7초). 프레임 0의 값도 확인했다: observation.state[0:3] = [0.0, 0.0, 0.0](elapsed_time/두 qpos 비율 전부 시작점), action[0:2] = [0.0, 0.0] — 시작 순간엔 우연히 같지만, 에피소드가 진행되며 목표(action)와 실측(observation)이 갈라지는 게 바로 이번 재설계의 목적이다.
3. 다음 단계
스키마 재설계는 데이터 생성 단계까지만 끝났다 — 아직 재학습·재검증 전이다. 다음 순서로 제안한다: 1. 새 16차원 스키마로 생산용 체크포인트 재학습. 2. Stage 2 방식(홀드아웃 폐루프)과 Stage 4 방식(다중 시드 스트레스 테스트) 둘 다로 재검증 — 이번엔 처음부터 여러 시드로 돌려 [[2026-08-20-moojoco-lerobot-stage4-stress-test]]의 "단일 시드 낙관값" 실수를 반복하지 않는다. 3. Aegis에게 다시 독립 재현 요청.
사령관 확인 후 재학습으로 진행한다.
v2 추가 — 새 스키마로 생산용 재학습 완료(검증은 아직)
저자: Moojoco (hb5u)
계기: 사령관 지시 "재학습부터 진행해줘."
일자: 2026-08-20 (v2 추가, v1 원문은 아래 그대로 보존)
분류: handshake-robot, result, moojoco, mujoco, lerobot
v2-1. 학습 결과
train_stage2_act_policy.py를 16차원 스키마·132개 에피소드(80개 게이트 통과)로 재실행했다.
| 항목 | 이전(15차원 스키마) | 이번(16차원 스키마) |
|---|---|---|
| 학습 샘플 | 6,490 | 6,490(동일 에피소드 수) |
| 에폭 | 200 | 200 |
| 최종 loss | 0.019 | 0.0093 |
| 학습 시간 | 2,543초 | 2,549초 |
| 최대 VRAM | 196.8MB | 196.8MB |
체크포인트: data/lerobot_stage2_act_policy/checkpoint/(이전 15차원 스키마 체크포인트를 덮어씀).
v2-2. 아직 결론 내리지 않는다
[[2026-08-20-moojoco-lerobot-stage4-stress-test]] v2에서 배운 교훈을 그대로 적용한다 — loss가 낮다는 것도, 단일 실행 결과도 안전성의 증거가 아니다. 이번 loss(0.0093)가 이전(0.019)보다 낮은 건 스키마 재설계로 관찰-행동 항등함수 지름길이 사라져 학습이 더 명확한 신호를 갖게 됐다는 신호로 해석할 수는 있지만, 그 자체가 폐루프 성능을 보장하지 않는다는 걸 이미 두 번(Stage 2 최초 검증, Stage 3 거짓양성) 확인했다.
다음 단계로 Stage 2(홀드아웃 폐루프)와 Stage 4(다중 시드 스트레스 테스트) 방식의 재검증을 진행해야 하며, 이번엔 처음부터 여러 시드로 돌려 단일 시드 낙관값 실수를 반복하지 않는다. 사령관 확인 후 진행한다.
v3 추가 — 다중 시드 스트레스 테스트: 58.7% (구 스키마 32%보다 크게 개선, 편차도 줄어듦)
저자: Moojoco (hb5u)
계기: 사령관 "응"(다중 시드로 재검증 진행 승인). [[2026-08-20-moojoco-lerobot-stage4-stress-test]] v2에서 Aegis가 단일 시드 발표치(46%)를 3시드 평균(32%)으로 REJECTED 판정했던 교훈을 반영해, 이번엔 stage4_stress_test_policy.py 자체를 처음부터 다중 시드 루프로 고쳐서 실행했다.
일자: 2026-08-20 (v3 추가, v1/v2 원문은 아래 그대로 보존)
분류: handshake-robot, result, moojoco, mujoco, lerobot, verification
v3-1. 스크립트 변경
run_stage2_policy_live.py/stage4_stress_test_policy.py의 관찰 조립을 새 16차원 스키마(elapsed_time_frac + handA/B_qpos_frac)로 맞췄다. 스트레스 테스트는 시드 하나로 끝내지 않고 세 시드(20260821, 20260820 — Aegis가 쓴 시드 중 하나와 겹침, 555555)를 순서대로 돌려 시드별 결과와 3-시드 평균을 함께 보고하도록 바꿨다.
v3-2. 결과
| 시드 | 통과율 |
|---|---|
| 20260821 | 58.0% |
| 20260820 | 62.0% |
| 555555 | 56.0% |
| 3-시드 평균 | 58.7% |
150개 전부 genuinely_engaged(퇴화 no-op 아님) 확인.
| 비교 | 구 스키마(15차원, Aegis 검증) | 새 스키마(16차원, 이번) |
|---|---|---|
| 시드별 통과율 범위 | 26%~50% (24%p 편차) | 56%~62% (6%p 편차) |
| 평균 통과율 | 32.0% | 58.7% |
평균이 32%→58.7%로 크게 올랐을 뿐 아니라, 시드 간 편차도 24%p→6%p로 훨씬 안정적이다 — 관찰-행동 항등함수 지름길을 없앤 스키마 재설계가 성능과 재현성 양쪽에 실제로 도움이 됐다는 증거로 해석한다.
v3-3. 다음 단계
- 홀드아웃 폐루프 방식(Stage 2 스타일) 다중 시드 검증은 시드마다 전체 재학습이 필요해(각 15~25분) 비용이 크다 — 이번 스트레스 테스트 결과가 충분히 강하고 일관적이라고 판단해, 우선 이 결과를 Aegis에게 다시 독립 재현 요청한다.
- Aegis 재현 결과를 받은 뒤 홀드아웃 다중 시드까지 필요한지 사령관과 논의한다.
