학습·선택·시험의 역할을 먼저 고정한다
학습은 train 관측/행동으로 파라미터를 맞추는 단계다. validation은 모델/하이퍼파라미터와 checkpoint 선택에 쓰고, test는 고정한 선택의 최종 확인에 남겨 둔다. checkpoint는 파라미터만이 아니라 어떤 입력/행동 표현·정규화/모델 설정으로 해석할지의 계약과 연결된다. 같은 가중치라도 카메라/관절 순서나 action 역변환이 달라지면 다른 정책이 된다.
학습을 중단했다가 이어 가는 resume와 학습된 정책으로 추론만 하는 것은 다른 작업이다. 전자는 목적에 따라 optimizer/학습률 스케줄·반복 위치/난수 상태와 데이터 순서도 필요할 수 있다. 후자는 모델 구조/가중치와 전후처리·입력/행동 스키마가 필요하다. 어느 상태를 저장했는지 확인하지 않고 파일 하나로 완전 재현을 보장하지 않는다.
LeRobot 공식 모방학습 경로는 수집·학습/저장과 추론/평가를 구분한다. 실제 모델을 사용할 때 데이터/코드·모델 revision과 checkpoint 선택 근거를 기록한다. 이 단위에서는 해당 명령을 실행하지 않고 작은 정책으로 루프의 의미를 확인한다.
작은 맞춤 예로 손실과 행동의 관계를 본다
모든 값이 무차원인 교육용 1차원 문제를 정한다. 상태 x는 정규화 위치, action u는 한 논리 제어 단계의 위치 증분이다. 관측은 x 그 자체이고 다음 상태는 x_next=x+u다. 마찰/접촉·영상/통신 지연이나 실제 관절/기구학이 없는 단순 모형이다. 물리 로봇의 m/rad 명령으로 복사하지 않는다.
train의 상태는 0.0/0.1/0.2, action은 각각 0.1이다. 입력에 관계없이 항상 c를 내는 제한된 정책 클래스를 택한다. 제곱 손실 평균을 최소로 하는 상수는 action의 평균이므로 c=0.1이다. 세 잔차가 모두 0이라 train MSE는 0이다. 이는 닫힌 식으로 맞춘 소형 BC 예이지 심층 모델을 학습했다는 뜻이 아니다. 상태에 따라 방향을 바꾸는 규칙은 이 정책 클래스가 표현하지 못한다.
과업 목표는 x=1.0에 오차 0.01 이하로 도달하는 것이고, 시작부터 검사하며 최대 5개 action까지 적용한다. action 크기는 0.1 이하로 제한한다. 성공하면 즉시 종료한다. 한 action의 논리 간격은 0.1 s로 정의하지만 CPU wall time/실제 제어 주기를 뜻하지 않는다. 개발 진단용 시작값 0.6/1.1을 주어 보자.
rollout은 새 상태를 다시 정책에 넣는 과정이다
rollout은 시작 상태에서 정책의 행동을 적용하고 다음 관측을 다시 입력하며 한 시도를 진행하는 것이다. 저장된 frame을 읽어 action 오차만 계산하는 offline 검증과 다르다. 이 예의 시작 0.6에서는 0.6→0.7→0.8→0.9→1.0으로 4번 적용 후 성공한다. 논리 시간은 0.4 s다.
시작 1.1은 이미 목표보다 큰데 상수 정책은 계속+0.1을 낸다. 1.1→1.2→1.3→1.4→1.5→1.6으로 5번 뒤에도 실패하고 논리 시간 0.5 s다. train 손실 0이었어도 이 상황을 해결하지 못한다. 두 시작 모두 train 상태 범위 밖이지만 하나는 성공하므로 '미관측 범위면 반드시 실패'라는 결론도 아니다. 단일 성공의 외삽과 일반화 보장을 구분한다.
아래는 이 문제의 완전한 선택 예제다. 표준 Python만 사용하며 난수/외부 파일이나 장비 연결이 없다.
train_states = [0.0, 0.1, 0.2]
train_actions = [0.1, 0.1, 0.1]
c = sum(train_actions) / len(train_actions)
train_mse = sum((c - a) ** 2 for a in train_actions) / len(train_actions)
def rollout(start, max_steps=5):
x = start
path = [round(x, 3)]
for step in range(max_steps + 1):
if abs(x - 1.0) <= 0.01:
return True, step, path
if step == max_steps:
return False, step, path
u = max(-0.1, min(0.1, c))
x += u
path.append(round(x, 3))
print(f"train_mse={train_mse:.3f}")
for start in [0.6, 1.1]:
ok, steps, path = rollout(start)
print(f"start={start:.1f} success={ok} steps={steps} path={path}")
출력은 다음과 같다. 표시용 round는 반환 경로의 출력에만 쓰며 내부 x를 매번 반올림해 갱신하지 않는다.
train_mse=0.000
start=0.6 success=True steps=4 path=[0.6, 0.7, 0.8, 0.9, 1.0]
start=1.1 success=False steps=5 path=[1.1, 1.2, 1.3, 1.4, 1.5, 1.6]
성공률에는 조건과 종료 이유를 붙인다
이 두 개발 시도의 성공률은 1/2=50%다. 실제 로봇 성능이나 새로운 시작 분포의 성공 확률을 추정한 값으로 쓰지 않는다. 실패 시도를 빼면 성공 1/1로 바뀌므로 분모를 반드시 남긴다. 성공한 경우의 논리 시간 0.4 s만 평균해 전체 요청 처리 시간이 0.4 s라고 보고하지 않는다. 실패의 0.5 s·초기화/대기와 도움 여부 등 포함 범위를 명시한다.
실제 과업에서는 성공·시간 초과·안전/제약 위반·관측 누락·사람 개입 같은 종료 이유를 분리한다. 도움 후 성공과 자율 성공도 다르다. 예를 들어 3시도 중 자율 성공 1/도움 후 성공 1/실패 1이라면 완료 2/3과 자율 1/3은 서로 다른 지표다. 시도 ID와 요청 ID·재시도, 비교 정책의 같은 초기 조건/과업과 환경 버전도 맞춰 기록한다.
실패에서 관찰 사실과 가설을 나눈다
위 모형의 관찰 사실은 시작 1.1에서 항상 양의 action을 내고 목표에서 멀어진다는 것이다. 이를 카메라/통신 고장이라고 부를 근거는 없다. 상수 정책의 표현 한계와 목표보다 큰 상태의 적절한 action 시연이 없다는 것이 이번 문제의 명시된 조건이다. 실제 로봇에서는 관측 오류·분포 이동/모드·기구학/지연·정규화·접촉/제한 등 여러 가설을 원본 로그/설정으로 구분해야 한다.
Ross 등의 순차 분포 논문처럼 정책이 방문한 상태는 이전 행동의 영향을 받는다. 추가 자료는 실패 화면을 많이 모으는 데서 끝나지 않는다. 어떤 관측 조건에서 어떤 행동이 적절한지, 누가 그 라벨을 제공/검증했는지와 시간/안전 조건이 필요하다. 실패한+0.1들을 다시 좋은 action으로 넣으면 같은 문제를 강화할 수 있다.
재수집은 데이터와 평가 계약을 함께 바꾼다
이번 예에서 목표 너머의 상태를 다루려면 그 영역의 적절한 관측-행동과 종료/복구 기준을 계획하고, 상태에 따라 다른 action을 표현할 수 있는 정책 클래스를 검토한다. 적절한 라벨을 검증한 뒤 원본/개입 구간·group과 새 데이터 revision을 남긴다. 기존 자료의 균형/통계·동작 범위와 망각/회귀도 확인한다. 단순히 더 오래 학습하는 것만으로 표현/라벨 결함이 해결된다고 보장하지 않는다.
개발 롤아웃 0.6/1.1을 보고 정책을 수정했다면 그 조건들은 개발/회귀 검사로 사용할 수 있다. 이후 같은 두 값에서 좋아졌다고 손대지 않은 독립 시험 성공이라고 부르지 않는다. scikit-learn 공식 누수 지침의 분할 원칙처럼 선택에 사용한 정보를 최종 시험과 분리한다. 별도 잠근 원본 그룹/조건과 평가 기준으로 새 결과를 확인한다.
루프의 기록은 데이터/정책/전후처리 버전→선택 근거→개발 실행 조건/결과→실패 가설/근거→재수집·라벨/분할 변경→재검증으로 이어진다. 중간의 미상/실패를 보존해야 어느 변경이 도움이 되었는지 비교할 수 있다. 기존 5.8 학습 루프와 기존 5.10 평가에서 실제 프로젝트의 검증 계층을 연결해 읽자.