Index
2026-10-09 — Walkthrough

영상으로 보는 시도-적응 게이트 실험

try-and-suc | 무엇을, 어떤 데이터로, 어떻게 학습했고, 학습된 정책이 실제로 무엇을 하는가

TL;DR

60,000
학습 에피소드
2.4M
저장 프레임
87.5 / 89.9%
보간 @3 (퍽/공)
0.0%
기억 없는 정책

1 문제: 같은 타격, 다른 결과

테이블 위 물체를 한 번 쳐서 빨간 목표 원 안에 멈추게 한다. 아래 네 칸은 완전히 같은 타격이다. 바뀐 것은 화면에 보이지 않는 물성 하나뿐이다.

목표 원(반경 6cm)퍽 / 공주황 선: 명령한 타격(방향, 길이 ∝ 임펄스 J)회색 ×: 이전 시도가 멈춘 곳초록/빨강 고리: 성공/실패
physics_puck.webp
퍽 밀기. 왼쪽부터 기준 물성(성공), 마찰만 낮춤(57cm 지나침), 질량만 올림(31cm 못 미침), 테이블만 오른쪽으로 3° 기울임(7cm 옆으로 빠짐). 학습 범위의 양 끝 값을 썼다.
physics_ball.webp
공 굴리기. 같은 구성. 공은 구름 저항과 질량, 경사가 숨은 변수다.

카메라는 테이블에 고정된 탑다운 시점이고 경사는 중력 방향을 기울여 구현했기 때문에, 정지 화면만 봐서는 물성을 알 수 없다. 물성은 쳐 본 뒤 물체가 어떻게 움직였는지로만 드러난다. 그래서 첫 시도는 누구라도 찍을 수밖에 없고, 승부는 두 번째 시도부터다.

숨은 변수학습 범위처음 보는 범위(보간)범위 밖(외삽)
퍽 미끄럼 마찰0.15–0.400.30–0.360.11–0.15, 0.40–0.48
퍽 질량 [kg]0.15–0.300.24–0.270.12–0.15, 0.30–0.36
퍽 경사 [°]0–3.01.2–1.83.0–3.6
공 구름 저항0.08–0.200.15–0.180.06–0.08, 0.20–0.24
공 질량 [kg]0.08–0.160.13–0.1450.064–0.08, 0.16–0.19
공 경사 [°]0–1.50.6–0.91.5–1.8

보간 범위는 학습 데이터에서 통째로 뺀 띠다. 경사 방향은 항상 0–360° 무작위. 같은 명령에도 실행 노이즈(임펄스 3%, 방향 1.5°)가 매번 섞인다.

2 학습 데이터: 시도 시퀀스

한 에피소드는 숨은 물성과 시작/목표 배치가 고정된 채 5번 치는 것이다. 과제당 30,000 에피소드(학습 29,000 + 검증 1,000), 합쳐서 300,000번의 시도, 2,400,000 프레임(110GB)을 MuJoCo로 만들었다.

각 클립의 왼쪽은 데이터에 저장된 시도들(모델이 "과거 시도"로 보게 되는 것), 오른쪽은 그 에피소드의 정답 라벨인 오라클 타격을 5번 실행한 것이다.

목표 원(반경 6cm)퍽 / 공주황 선: 명령한 타격(방향, 길이 ∝ 임펄스 J)회색 ×: 이전 시도가 멈춘 곳초록/빨강 고리: 성공/실패

(a) 60%: 파티클 필터 교사 — "실패, 조금 나은 시도, 성공"

1차는 평균 물성을 가정한 타격. 이후 관측한 궤적과 맞는 물성 후보(파티클 1,024개)만 남기고, 그 평균 물성 기준 최적 타격을 낸다. 교사의 누적 성공률은 시도별로 약 8 → 56 → 82 → 91 → 95%.

data_puck_teacher.webp
퍽, 교사 시퀀스 (마찰 0.365, 질량 0.151kg, 경사 2.04°). 3차에 성공. 저장 시퀀스 중 '3차에 처음 성공한 첫 번째 교사 에피소드'를 골랐다.
data_ball_teacher.webp
공, 교사 시퀀스 (구름 저항 0.194, 질량 0.157kg, 경사 0.32°).

(b) 40%: 오라클 타격에 무작위 오차를 넣은 시도

교사만 쓰면 실패가 점점 작아지는 시퀀스만 보게 된다. 크고 작은 실패가 섞인 컨텍스트도 보도록 임펄스에 3–50%, 방향에 그에 비례하는 무작위 오차를 넣었다.

data_puck_random.webp
퍽, 무작위 섭동 시퀀스 (마찰 0.230, 질량 0.172kg, 경사 2.20°).
정답 라벨(오라클 타격 a*): 진짜 물성을 알고, 노이즈가 없을 때 정확히 목표에 멈추는 타격. 해석 모델로 초기값을 구한 뒤 MuJoCo에서 4회 보정했다. 남은 오차 평균 0.01cm.
중요: 모델은 왼쪽 시퀀스를 따라 하도록 학습하지 않는다. 왼쪽은 "읽을거리"이고, 맞혀야 하는 답은 언제나 오른쪽의 a*다.

3 정책이 실제로 받는 입력

위 클립은 보기 좋게 256px·10fps로 다시 그린 것이다. 모델이 받는 것은 아래처럼 128×128 RGB, 시도당 8프레임이다(t = 0, 0.1, 0.2, 0.4, 0.7, 1.1, 1.6초, 그리고 정지 후). 프레임 시각이 고정이라 프레임 사이 이동 거리에서 속도와 감속을 읽을 수 있다.

입력 프레임
학습 데이터의 한 에피소드. 한 줄이 시도 1회(8프레임), 위에서부터 1·2·3차 시도. 실제 저장된 픽셀을 2배 확대.
현재 이미지치기 전 한 장(128×128). 시작 위치와 목표 위치를 여기서 읽는다.
+
과거 시도 k개 (0–4)시도마다 영상 8프레임 + 그때 명령한 타격 (J, 방향).
→
CNN + 트랜스포머이미지 CNN → 질의 토큰. 시도마다 영상 CNN(8프레임을 24채널로 쌓음) + 타격 MLP → 토큰 1개. 4층 트랜스포머(d=256, 4헤드).
→
출력다음 타격 (log J, 방향) 2개 숫자.

정책에 주어지지 않는 것: 마찰·질량·경사, 목표나 물체의 좌표 숫자, 오차 숫자. 주 모델은 영상과 자기가 명령한 타격만 본다.

4 무엇을 어떻게 학습했나

학습 문제: (현재 이미지, 과거 시도 k개) → 오라클 타격 a*를 맞히는 회귀. 배치마다 에피소드별로 k를 0–4에서 무작위로 골라, 저장된 시퀀스의 앞 k개 시도만 보여 준다.

손실: 정규화한 (log J, 방향)에 대한 MSE 최적화: AdamW, lr 3e-4 (워밍업 1,000 step + 코사인), weight decay 0.01, batch 256, bf16, EMA 0.999 학습량: 12,000 step, 500 step마다 검증 → 검증 최고점 체크포인트 사용 (주 모델 3,500 step, 기억 없는 정책 500 step) 한 모델이 퍽과 공을 모두 학습 (과제 구분 입력 없음, 이미지로 구분) 소요: 모델당 B200 1장으로 5–10분
검증 오차 (주 모델)과거 시도 0개1개2개4개
임펄스 오차 (log J RMSE)0.2510.0470.0250.018
방향 오차 (RMSE)2.89°1.61°1.00°0.75°

log J 0.25는 임펄스가 약 25% 틀린다는 뜻이고 정지 거리로는 약 50%다. 시도 하나를 보면 약 5%, 둘을 보면 약 2.5%로 줄어든다.

비교 대상(기억 없는 정책): 같은 에피소드, 같은 라벨, 같은 구조로 학습하되 과거 시도를 전혀 못 보게 한 모델. 차이는 컨텍스트뿐이다.

학습 중 발견한 문제: 이미지(시작·목표 배치)가 에피소드를 식별하기 때문에 오래 학습하면 학습 에피소드별 정답을 통째로 외운다. 그래서 모든 모델을 검증 최고점 체크포인트로 평가했다.

5 학습된 정책이 실제로 하는 것 (처음 보는 물성)

세 칸은 같은 에피소드(같은 숨은 물성, 같은 실행 노이즈)다. 왼쪽 오라클은 물성을 알고 치는 상한선, 가운데가 히스토리 정책, 오른쪽이 기억 없는 정책. 시도 1–5가 차례로 재생된다. 평가 시드의 처음 세 에피소드를 고르지 않고 그대로 실었다.

목표 원(반경 6cm)퍽 / 공주황 선: 명령한 타격(방향, 길이 ∝ 임펄스 J)회색 ×: 이전 시도가 멈춘 곳초록/빨강 고리: 성공/실패

볼 점: 가운데 칸의 주황 선(타격 세기와 방향)이 시도마다 바뀌는지, 오른쪽 칸은 5번 내내 같은 타격을 반복하는지.

policy_puck_interp_0.webp
퍽 #0 (마찰 0.315, 질량 0.257kg, 경사 1.59°). 히스토리 정책 4차에 성공, 기억 없는 정책 5번 모두 실패.
policy_puck_interp_1.webp
퍽 #1 (마찰 0.338, 질량 0.243kg, 경사 1.67°). 히스토리 정책 2차에 성공.
policy_puck_interp_2.webp
퍽 #2 (마찰 0.327, 질량 0.243kg, 경사 1.45°). 히스토리 정책 4차에 성공.
policy_ball_interp_0.webp
공 #0 (구름 저항 0.173, 질량 0.133kg, 경사 0.86°). 히스토리 정책 3차에 성공.
policy_ball_interp_1.webp
공 #1 (구름 저항 0.169, 질량 0.137kg, 경사 0.61°). 히스토리 정책 2차에 성공.
policy_ball_interp_2.webp
공 #2 (구름 저항 0.179, 질량 0.138kg, 경사 0.80°). 히스토리 정책 3차에 성공.

이 12개 에피소드 묶음에서 히스토리 정책이 처음 성공한 시도는 퍽 [4, 2, 4, 4, 3, 2, 2, 4, 2, 3, 3, 3], 공 [3, 2, 3, 3, 3, 2, 2, 2, 2, 4, 2, 3]이다. 기억 없는 정책은 24개 모두 5번 안에 성공하지 못했다. 첫 시도는 두 정책이 같은 타격을 낸다.

6 정말 과거 시도를 읽고 있는가

왼쪽은 자기 시도를 본 경우, 오른쪽은 배치는 같지만 물성이 다른 에피소드의 시도 기록을 보고 낸 타격을 원래 에피소드에 적용한 경우다. 같은 모델, 같은 가중치다.

shuffle_puck_0.webp
퍽 #0. 자기 히스토리로는 4차에 성공, 다른 물성의 히스토리로는 엉뚱한 쪽으로 고쳐 가며 5번 모두 실패.

1,000 에피소드로 재면 처음 보는 범위의 격차 +88.7%p가 이 조작으로 +8.2%p까지 줄고, 히스토리를 아예 지우면 0.0%p가 된다.

7 실패하는 경우: 범위 밖 물성

policy_puck_extrap_fail.webp
퍽, 외삽 (마찰 0.449, 질량 0.351kg, 경사 3.46° — 셋 다 학습 범위 밖). 히스토리 정책이 5번 안에 못 맞힌 첫 번째 에피소드를 일부러 골랐다(이 묶음 12개 중 5개 실패).

고치는 방향은 맞지만 학습에서 본 적 없는 크기까지 과감하게 올리지 못한다. 1,000 에피소드 기준 외삽 3차 성공률은 퍽 45.8%, 공 60.0%로, 수치 궤적을 쓰는 파티클 필터 교사(80.8%, 78.2%)보다 뚜렷이 낮다.

8 전체 수치

누적 성공률
시도 횟수별 누적 성공률. 조건당 1,000 에피소드(LLM 튜너만 100), 띠는 95% 신뢰구간.
3차까지 누적 성공률 (%)학습 범위 (퍽/공)보간 (퍽/공)외삽 (퍽/공)
오라클98.9 / 99.299.3 / 98.998.2 / 99.3
히스토리 정책 (영상+타격)87.1 / 87.587.5 / 89.945.8 / 60.0
영상만 (타격 기록 없음)31.7 / 33.757.3 / 60.62.5 / 2.1
IRP식 (과제 전용, 수치)84.4 / 85.583.5 / 84.177.9 / 81.7
ICPI식 LLM 튜너 (수치, N=100)—82.0 / 88.075.0 / 68.0
기억 없는 정책16.8 / 15.30.0 / 0.02.9 / 1.7

읽는 법

"기억이 있으면 된다"는 것은 크게 확인됐다. 다만 수치 오차를 직접 받는 기존 방식(IRP식, LLM 튜너)도 이 과제에서는 비슷하게 잘 하고 외삽은 더 낫다. 타격이 숫자 2개이고 결과가 정지 위치 하나로 요약되기 때문이다. 영상만 주고 타격 기록을 빼면 크게 떨어지는 점은, 과거에 무엇을 했는지가 컨텍스트에 반드시 있어야 함을 보여 준다. 보간 범위에서 기억 없는 정책이 0%인 것은 그 범위를 평균 물성에서 벗어난 곳에 잡았기 때문이며, 위치에 덜 의존하는 비교는 학습 범위 열(87 대 16)이다.

단순화: 행동은 타격 파라미터 2개, 타격은 이상적 임펄스(로봇 팔 없음), 학습 시드 1개. 클립 생성: python -m scripts.make_walkthrough. 전체 표: results/summary.md.