|
|
0. 들어가기 전에 - 사전 지식
0-1. VLA (Vision-Language-Action) 모델이란
전문 설명
로봇이 시각 관측(Vision), 자연어 지시(Language)를 입력받아 연속적인 제어 명령(Action)을 end-to-end로 출력하는 모델. 기존의 "인식 → 계획 → 제어" 파이프라인을 하나의 신경망으로 통합한 접근이다.
쉽게 다시 말하면
로봇이 눈으로 보고(카메라), 귀로 듣고(사람의 지시), 손발을 움직이는(관절 제어) 것을 하나의 뇌가 통째로 처리하는 것. 예전에는 "물체 인식하는 프로그램", "경로 계획하는 프로그램", "모터 제어하는 프로그램"이 따로따로였다면, 이것은 하나로 합친 것이다.
0-2. 트랜스포머와 토큰
전문 설명
트랜스포머는 입력을 토큰(token) 시퀀스로 받아, self-attention으로 토큰 간 상호 의존성을 모델링하는 구조다. 각 토큰은 고정 차원의 벡터로 표현되며, 시퀀스는 (토큰 개수 × 차원)의 행렬 형태를 갖는다.
쉽게 다시 말하면
"토큰"은 데이터를 잘게 쪼갠 조각 하나를 말한다. 문장이면 단어 하나, 이미지면 작은 사각형 패치 하나다. 이 조각들을 세로로 쭉 쌓으면 행렬이 되고, 트랜스포머는 이 행렬을 받아서 "어떤 조각이 어떤 조각과 관련 있는지" 계산한다.
중요한 용어 확장
π0 논문은 "token"이라는 단어를 시퀀스 차원의 한 슬롯을 가리키는 말로 확장해서 쓴다. 즉 언어 토큰(이산적 값)뿐 아니라 이미지 패치나 로봇 액션(연속적 값)까지도 전부 "토큰"이라고 부른다.
1. π0 전체 구조 한눈에 보기
π0는 크게 두 개의 신경망 덩어리로 구성된다.
| PaliGemma (VLM 백본) | 이미지 + 언어를 이해 | 약 30억 (3B) |
| Action expert | 이해한 것을 로봇 동작으로 변환 | 약 3억 (300M) |
| 합계 | 약 33억 (3.3B) |
구성요소 역할 파라미터 수
여기에 flow matching이라는 생성 알고리즘이 action expert를 반복 호출하며 최종 액션을 만들어낸다.
전체 데이터 흐름 (7단계)
1. 입력 (이미지 + 언어 + state) ↓
2. PaliGemma (VLM 백본) - 이해 ↓
3. Action expert - 방향 계산 (부품) ↓
4. Flow matching - 부품을 10번 반복 호출 (절차) ↓
5. 액션 청크 출력 (50스텝) ↓
6. 로봇 실행 ↓
7. 재입력 → 다시 1번으로 (compounding error 발생 지점)
2. [블록 1] 입력 - 세 가지 모달리티
2-1. 기능
전문 설명
관측 o_t = [I_t^1, ..., I_t^n, ℓ_t, q_t]는 다중 RGB 이미지, 언어 명령 토큰 시퀀스, 그리고 로봇의 proprioceptive state(관절 각도 벡터)로 구성된다.
쉽게 다시 말하면
로봇에게 주는 정보는 딱 세 가지다.
2-2. 카메라 이미지 - 몇 장이고 왜 그런가
구현 방식
로봇당 2~3장의 이미지를 사용한다. 개수가 다른 이유는 로봇의 팔 개수 때문이다.
| 손목(wrist) 카메라 | 팔 개수만큼 (1~2개) | 그리퍼가 물체를 정확히 어떻게 잡는지 근접 관찰 |
| 몸통/어깨너머(base) 카메라 | 보통 1개 | 전체 작업 공간과 상황 파악 |
카메라 위치 개수 역할
쉽게 다시 말하면
전체 상황을 보는 눈 1개 + 각 손끝을 보는 눈 N개(팔 개수만큼)
팔이 하나면 2장(손끝 1 + 전체 1), 팔이 둘이면 3장(왼손끝 1 + 오른손끝 1 + 전체 1). "이미지가 많으면 더 잘 본다"가 아니라, 팔이 늘어난 만큼 감시할 손끝이 늘어난 것뿐이다.
카메라가 3개 미만인 로봇은 빠진 이미지 슬롯을 마스킹(mask out) 처리해서 형식을 통일한다.
2-3. 언어 지시 - 두 가지 층위
전문 설명
Pre-training 데이터의 언어 라벨은 두 종류로 구성된다.
쉽게 다시 말하면
단어 단위가 아니라, 각각이 완전한 지시문이라는 점이 중요하다.
High-level policy와의 연결
사람이 "테이블 치워"라는 큰 지시만 주면, 별도의 상위 VLM(π0 자체가 아님)이 이것을 세부 지시로 쪼개주고, π0는 쪼개진 지시를 받아 실행만 담당한다. 논문은 이 방식이 SayCan과 유사하다고 언급한다.
SayCan이란: "Say"(언어모델이 그럴듯하다고 생각하는 계획)와 "Can"(로봇이 실제로 할 수 있는지)을 곱해서 다음 행동을 고르는 기존 방법론이다.
주의: π0 원 논문에는 이 high-level VLM의 구체적 알고리즘이 나오지 않는다. "SayCan과 유사한 방법론"이라는 언급이 전부다. 후속 모델인 π0.5(arXiv:2504.16054)에서는 이 부분이 개선되어, 별도 모델을 쓰지 않고 같은 모델이 2단계 추론(먼저 하위 목표를 추론 → 그 목표를 조건으로 액션 생성)을 수행하며, 고수준 추론은 저수준 액션보다 낮은 빈도로 실행된다.
2-4. 로봇 state - 차원이 다른 로봇들을 어떻게 통일하나
전문 설명
Configuration 벡터 q_t와 action 벡터 a_t는 항상 데이터셋에서 가장 큰 로봇의 차원(18차원)을 갖는다. 18차원은 두 개의 6-DoF 팔 + 2개의 그리퍼 + 모바일 베이스 + 수직 구동 몸통을 수용하기 위한 크기다. 더 낮은 차원의 로봇은 zero-padding으로 채운다.
쉽게 다시 말하면
로봇마다 관절 개수가 다르다. 팔 하나짜리는 7개, 팔 두 개짜리는 14개, 이동하는 로봇은 17~18개다. 그런데 신경망은 입력 크기가 항상 같아야 한다.
그래서 가장 큰 로봇 기준(18칸)으로 그릇을 만들어두고, 작은 로봇은 남는 칸을 0으로 채운다.
7차원 로봇: [관절1, 관절2, ..., 관절7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] (11칸을 0으로 채움)
중요한 정정: 제로 패딩하면 로봇끼리 호환되는가?
아니다. 제로 패딩은 입력 형식(크기)만 맞춰주는 기술적 트릭이다.
그럼 왜 여러 로봇 데이터가 도움이 되는가? VLM 부분(시각/언어 이해)이 로봇 종류와 무관하게 공유되기 때문이다. "빨간 블록이 저기 있고, 저것을 집으라는 뜻이구나"라는 이해는 어떤 로봇이든 똑같이 쓸 수 있다. 다만 그 이해를 특정 로봇의 관절 움직임으로 변환하는 부분은 그 로봇 데이터를 봐야 배울 수 있다.
2-5. 세 입력이 하나의 행렬이 되기까지
전문 설명
각 모달리티는 서로 다른 인코더를 거쳐 동일한 임베딩 차원으로 선형 투영(linear projection)된 후, 하나의 토큰 시퀀스로 concatenate된다.
| 이미지 | SigLIP 비전 인코더 | 패치 토큰 여러 개 |
| 언어 | 텍스트 토크나이저 | 단어 토큰 여러 개 |
| State | 선형 투영 레이어 (MLP) | 토큰 1개 |
입력 처리 도구 결과
쉽게 다시 말하면
셋 다 결국 "같은 길이의 벡터"로 변환된다. 다만 변환하는 도구가 각각 다르다. 이미지는 이미지 전용 도구, 언어는 언어 전용 도구, state는 또 다른 도구를 쓴다.
왜 길이를 맞춰야 하나? 트랜스포머는 모든 토큰(행)이 같은 길이여야 하나의 행렬로 쌓아서 계산할 수 있기 때문이다.
최종 입력 행렬 (한 행 = 한 토큰)
[이미지 토큰 1 ] ← 이미지가 보통 가장 많은 행을 차지 [이미지 토큰 2 ] [ ... ] [언어 토큰 1 ] ← 문장 길이에 따라 개수가 달라짐 [언어 토큰 2 ] [ ... ] [state 토큰 ] ← 보통 1개로 압축됨
각 종류가 차지하는 행의 개수는 서로 다르다. 이미지가 가장 많고, state는 보통 1개다.
SmolVLA와 동일한 부분
"입력을 각각 다른 방법으로 처리한 뒤 같은 공간으로 모은다"는 이 골격은 SmolVLA와 완전히 동일하다. 차이는 인코더의 크기와, SmolVLA가 추가로 넣은 PixelShuffle 압축 단계 정도다.
3. [블록 2] PaliGemma - VLM 백본
3-1. 기능
전문 설명
PaliGemma는 SigLIP 비전 인코더와 Gemma 언어 디코더로 구성된 30억 파라미터 규모의 오픈소스 VLM이다. π0는 이를 late fusion VLM recipe에 따라 사용하며, 이미지 인코더가 이미지를 언어 토큰과 동일한 임베딩 공간으로 매핑한다. 인터넷 규모 사전학습으로 획득한 semantic knowledge를 상속받는 것이 목적이다.
정확한 하이퍼파라미터 (후속 논문 arXiv:2505.23705에서 확인)
| width (hidden dimension) | 2048 |
| depth (레이어 수) | 18 |
| mlp_dim (FFN 내부 차원) | 16,384 |
| num_heads | 18 |
| num_kv_heads | 1 |
| head_dim | 256 |
항목 값
쉽게 다시 말하면
이 부분이 로봇의 "이해하는 뇌"다. 인터넷에 있는 방대한 이미지-텍스트 데이터로 이미 학습이 끝난 상태로 가져오기 때문에, "빨간색이 무엇인지", "블록이 무엇인지", "집으라는 것이 무슨 뜻인지" 같은 상식을 이미 알고 있는 채로 시작한다.
3-2. 내부 동작 - Self-attention
전문 설명
입력 토큰 시퀀스에 대해 self-attention을 수행한다. 각 토큰은 시퀀스 내 모든 토큰과의 attention score를 계산하고, 그 가중치에 따라 다른 토큰의 정보를 자신의 표현에 가중합으로 반영한다.
쉽게 다시 말하면
각 토큰이 다른 모든 토큰을 쳐다보면서, "나는 얘와 얼마나 관련 있나"를 계산한다.
예를 들어 "빨간 블록을 집어라"라는 지시와 이미지가 함께 들어왔다면:
흔한 오해 정정: "토큰들이 뭉쳐서 모인다"?
자리(순서)는 바뀌지 않는다. 토큰의 위치는 그대로다. 바뀌는 것은 각 토큰이 담고 있는 벡터의 값(내용)이다.
즉, "이 언어 토큰의 벡터는 이제 관련된 이미지 토큰의 정보까지 흡수해서 더 풍부한 값이 됐다"는 것이지, 물리적으로 어딘가로 이동하는 것이 아니다.
3-3. 출력
입력과 똑같은 모양의 행렬이 나온다. 행 개수도, 각 행의 차원도 그대로다. 달라지는 것은 각 행에 담긴 숫자 값뿐이다.
이 출력이 다음 블록(action expert)으로 전달될 때 prefix라고 불린다.
4. [블록 3] Action expert - 방향을 계산하는 부품
4-1. 기능 - 이것이 정확히 무엇인가
전문 설명
Action expert는 로봇 특화 토큰(state, action)에 대해 별도의 가중치 세트를 갖는 트랜스포머다. 이는 두 개의 mixture element를 갖는 mixture of experts(MoE) 구조와 유사하다. 첫 번째 element는 이미지/텍스트 입력을, 두 번째 element(action expert)는 로봇 특화 입출력을 담당한다. 이 설계는 Transfusion 아키텍처에서 영감을 받았다.
정확한 하이퍼파라미터
VLM 백본과 동일한 구조를 쓰되, 크기만 다르다.
| width | 2048 | 1024 |
| depth (레이어 수) | 18 | 18 (동일) |
| mlp_dim | 16,384 | 4,096 |
| 파라미터 수 | 약 2.29B | 약 0.315B |
항목 VLM 백본 Action expert
즉 레이어 수는 같고, 각 층의 폭이 절반, FFN 내부 차원이 1/4이다.
쉽게 다시 말하면
Action expert = 나침반(도구/부품)
"지금 이 위치에서, 이 상황이면, 어느 방향으로 가라"고 알려주는 계산 도구 하나다.
뒤에 나올 flow matching과 헷갈리기 쉬운데, 명확히 구분하면:
4-2. 액션 토큰 - 출력을 담을 그릇
전문 설명
액션 청크 A_t = [a_t, ..., a_(t+H-1)] (H=50)의 각 액션에 대해 대응하는 action token이 존재하며, 이들이 action expert를 통과한다. 노이즈 낀 액션 청크는 MLP 레이어를 통해 트랜스포머의 임베딩 공간으로 매핑된다.
쉽게 다시 말하면
액션 토큰은 "앞으로 할 동작이 담길 빈 그릇"이다.
중요한 구분: 액션 토큰과 state 토큰은 다르다
| 의미 | 현재 자세 (지금 팔이 이 각도) | 앞으로 할 동작 (팔을 이렇게 움직여라) |
| 역할 | 입력 (이미 알고 있는 것) | 출력 (모델이 찾아내야 할 것) |
| 학습 시 초기값 | 실제 관측값 그대로 | 정답 액션 + 노이즈 |
| 추론 시 초기값 | 실제 관측값 그대로 | 순수 랜덤 노이즈 |
State 토큰 액션 토큰
4-3. 노이즈 - 왜 0이 아니라 랜덤인가
전문 설명
추론 시 A_t^0 ~ N(0, I)에서 시작한다. Flow matching은 액션의 연속적이고 다봉(multimodal)인 분포를 모델링하기 위한 것이며, 랜덤 노이즈는 이 분포에서 샘플링하기 위한 초기 시드 역할을 한다.
쉽게 다시 말하면
노이즈는 "방향"이 아니라 "출발 위치"다.
노이즈 자체는 방향 정보를 전혀 담고 있지 않다. 그냥 무작위 출발 좌표일 뿐이다. 방향은 action expert가 "이 위치 + 지금 상황"을 보고 매번 새로 계산해서 알려준다.
왜 0으로 고정하지 않는가?
로봇 조작은 정답이 하나가 아닌 경우가 많다. "컵을 집어라"에도:
0으로 고정하면 항상 똑같은 액션 하나만 나온다. 랜덤 노이즈에서 출발하면, 어떤 노이즈는 "왼쪽 정답" 쪽으로, 다른 노이즈는 "오른쪽 정답" 쪽으로 흘러갈 수 있다.
노이즈 = "이번에는 여러 정답 후보 중 어느 쪽으로 갈지"를 결정하는 무작위 씨앗(seed)
4-4. 내부 동작 - Attention 공유 + FFN 분리
이 부분이 π0 아키텍처의 핵심 설계다.
전문 설명
Action expert는 PaliGemma와 self-attention 메커니즘을 공유하되, feed-forward network(FFN)와 layer norm 가중치는 독립적으로 갖는다. 파라미터 이름 규칙상 PaliGemma는 llm_0, action expert는 llm_1로 구분된다.
구현 레벨에서는 각 레이어가 PaliGemma용(hidden_size=2048)과 Expert용(hidden_size=1024)의 별도 Q/K/V/O 투영 레이어를 갖고, 두 스트림의 query/key/value를 이어붙여서(concatenate) 함께 attention을 계산한다.
쉽게 다시 말하면
입력은 하나의 긴 행렬이다.
[PaliGemma가 처리한 이미지/언어/state 토큰들] ← prefix + [노이즈 낀 액션 토큰들] ← suffix
이 전체가 두 단계를 거친다.
1단계: Self-attention (공유) - "일단 다 모아본다"
왜 공유하나? 액션이 "지금 상황"을 참고해야 하니, 서로 정보를 주고받을 통로가 필요하기 때문이다.
2단계: FFN (분리) - "모아놓은 것을 보고 다시 정리한다"
FFN은 다른 토큰을 쳐다보지 않는다. 오직 자기 자신의 값만 가지고 계산한다.
FFN의 실제 계산:
핵심 통찰
왜 FFN을 분리하나? 이미지/언어를 이해할 때 "중요하다고 걸러낼 것"과, 액션(연속적인 물리 값)을 만들 때 "중요하다고 걸러낼 것"은 성격이 완전히 다르기 때문이다.
흔한 오해 정정: "FFN이 노이즈를 걸러내나?"
아니다. FFN은 그냥 범용적인 수학 변환 도구다.
"노이즈 제거"는 전체 구조(self-attention + FFN 반복 + flow matching)가 협력해서 만들어내는 최종 결과다.
4-5. Attention 마스크의 방향성 - 매우 중요한 설계
전문 설명
정보는 VLM에서 action expert로 단방향으로만 흐른다. VLM 임베딩은 action expert를 참조하지 않는다.
쉽게 다시 말하면 (1) - 왜 단방향인가
입력(이미지/언어 이해)이 결과(액션 토큰)를 참고하지 못하게 막아놓았다.
왜 막았는가? 액션 토큰은 flow matching 과정에서 매 스텝마다 계속 값이 바뀐다(노이즈에서 정답으로 이동하면서). 만약 이미지/언어 이해가 이 요동치는 값의 영향을 받는다면, "지금 무엇을 보고 있는지"에 대한 이해 자체가 매 스텝 흔들리게 된다.
단방향으로 막아두면 이미지/언어에 대한 이해는 안정적으로 한 번만 계산해두면 되고, 그래서 KV 캐싱(뒤에서 설명)이 가능해진다.
쉽게 다시 말하면 (2) - 왜 액션은 causal인가
Causal attention이란: 토큰이 자기보다 순서상 앞에 있는 토큰만 참고할 수 있고, 뒤에 있는 토큰은 못 보는 방식이다.
액션 청크는 [a_t, a_(t+1), ..., a_(t+49)]처럼 시간 순서가 있는 시퀀스다. 실제 세계에서 로봇은 1번째 동작을 먼저 하고, 그 다음 2번째 동작을 한다. 1번째 동작을 정할 때 "50번째에 무엇을 할지"를 미리 알고 정하는 것이 아니다.
Causal 제한이 없으면, 모델이 "미래에 이런 동작이 예정되어 있으니까 지금은 이렇게 해야지"라는 식으로 아직 일어나지 않은 정보에 기대는 계산을 하게 되는데, 이는 실제 로봇 실행 시에는 있을 수 없는 상황이다.
시계열 데이터에서 미래 정보가 과거로 새어 들어가면 안 된다는 원칙과 같은 개념이다.
반면 이미지 패치나 문장의 단어들은 순서가 시간적 인과관계를 의미하지 않는다. "빨간"이라는 단어가 "블록"보다 먼저 나왔다고 해서 원인이 되는 것이 아니므로, 서로 자유롭게 봐도 문제가 없다.
4-6. 다층 레이어 반복 + 잔차 연결
전문 설명
"Self-attention → FFN" 한 세트가 하나의 레이어를 구성하며, π0에서는 18개 레이어가 적층된다. 각 sub-layer에는 residual connection이 적용된다: 출력 = 입력 + Sublayer(입력)
쉽게 다시 말하면
왜 여러 번 반복하나? 한 번에 정교한 판단까지 도달하기 어렵기 때문이다.
연관 있는 것끼리 뭉쳐서, 무엇이 중요한지 차근차근 천천히 다듬어가는 과정이다.
잔차 연결(residual connection)이란?
계산은 "변화량"만 하고, 다음 층에는 "원본 + 변화량"을 그대로 넘겨준다.
레이어를 수십 개 쌓으면 정보가 너무 많이 변형되다가 원래 중요했던 정보가 사라질 수 있다. 그래서 원본 값을 계속 더해줘서 정보가 유실되지 않게 하는 안전장치다.
4-7. Timestep 정보를 어떻게 주입하나
전문 설명
π0는 flow matching timestep τ를 sine-cosine 임베딩으로 변환하여, suffix의 액션 토큰들과 함께 시퀀스에 포함시킨다(in-context conditioning 방식).
쉽게 다시 말하면
Flow matching은 10번 반복하면서 매번 "지금 몇 번째 스텝인지"를 신경망에 알려줘야 한다. 노이즈가 많이 낀 초반 스텝과 거의 정답에 가까운 후반 스텝에서는 계산해야 할 방향이 다르기 때문이다.
π0는 이 정보를 하나의 토큰처럼 만들어서 시퀀스에 끼워 넣는다. 그러면 self-attention 과정에서 액션 토큰들이 이 timestep 토큰도 자연스럽게 참고하게 된다. 별도의 특수한 장치 없이, 그냥 시퀀스에 넣는 것만으로 자동 반영되는 방식이다.
(참고: π0-small은 DiT 아키텍처를 쓰므로 AdaLN-Zero라는 다른 방식으로 timestep을 주입한다. 12장 참조)
4-8. 출력
전문 설명
모든 레이어를 통과한 후, 액션 토큰 위치에 해당하는 출력만 추출한다. 이 값이 v_θ(A_t^τ, o_t), 즉 학습된 벡터장(velocity field)이다.
쉽게 다시 말하면
이 값이 의미하는 것: "지금 이 위치(노이즈 낀 액션)에서, 목적지(정답 액션)를 향해 어느 방향으로 얼마나 움직여야 하는가"
5. [블록 4] Flow matching - 부품을 반복 호출하는 절차
5-1. 기능
전문 설명
Conditional flow matching은 연속적인 액션 분포를 모델링하는 생성 알고리즘이다. Diffusion의 변형(variant)으로, linear-Gaussian(optimal transport) probability path를 사용한다.
쉽게 다시 말하면
Flow matching = 나침반(action expert)을 10번 보면서 목적지까지 가는 전체 여행 절차
5-2. 학습 (Training)
전문 설명
Loss 함수: L^τ(θ) = E[ || v_θ(A_t^τ, o_t) - u(A_t^τ | A_t) ||² ]
노이즈 낀 액션 계산 (openpi 코드 기준): x_t = t · noise + (1 - t) · actions
목표 벡터장 (openpi 코드 기준): u_t = noise - actions
Timestep 샘플링: t ~ Beta(1.5, 1) 분포에서 샘플링하며, 노이즈에 가까운 구간(t=1 근처)에 집중된다.
논문에서는 cutoff 값 s = 0.999 이상의 timestep은 샘플링하지 않는다고 명시한다.
쉽게 다시 말하면
학습은 이렇게 진행된다:
중요한 정정: flow matching은 loss 없이 감으로 그리는 것이 아니다
Flow matching도 엄연히 명확한 loss를 정의하고, 경사하강법으로 그 loss를 최소화하는 지도학습이다. 차이는 "무엇을 예측하도록 학습하느냐"일 뿐이다.
왜 노이즈를 다양한 비율로 섞나?
"노이즈 → 정답"으로 가는 길 전체를 배워야 하기 때문이다. 길의 여러 지점(노이즈 많은 곳, 적은 곳)에서 각각 "여기서는 이 방향"을 다 배워둬야 나중에 어디서 출발해도 목적지를 찾아갈 수 있다.
왜 노이즈 많은 구간(t=1 근처)에 집중해서 샘플링하나?
노이즈가 많은 초반 구간이 더 어렵고 중요한 구간이기 때문이다. 거의 정답에 가까운 후반 구간은 미세 조정만 하면 되므로 상대적으로 쉽다.
5-3. 추론 (Inference)
전문 설명
학습된 벡터장을 τ=0에서 τ=1까지 적분한다. Forward Euler 적분 규칙을 사용한다:
10회의 적분 스텝(δ = 0.1)을 사용한다.
최적화: prefix o_t에 대한 attention의 key/value를 캐싱하고, 각 적분 스텝마다 액션 토큰에 해당하는 suffix만 재계산한다.
쉽게 다시 말하면
안개 속에서 목적지를 찾아가는 것과 같다.
A⁰(노이즈) → A⁰·¹ → A⁰·² → ... → A¹(최종 액션) ↑ 매번 action expert를 호출해서 방향을 받음
KV 캐싱이란?
이미지/언어 정보(prefix)는 10번 반복하는 동안 전혀 바뀌지 않는다. 그래서 첫 번째 계산 결과를 저장해두고 재사용한다. 매번 다시 계산하는 것은 액션 토큰 부분(suffix)뿐이다.
이것이 가능한 이유가 바로 4-5장에서 설명한 "정보가 VLM → action expert 단방향으로만 흐른다"는 설계 때문이다. 만약 양방향이었다면 액션 토큰이 바뀔 때마다 prefix도 다시 계산해야 해서 캐싱이 무의미해진다.
6. [블록 5] 액션 청크 출력
6-1. 기능
전문 설명
Flow matching의 최종 출력은 action chunk A_t = [a_t, a_(t+1), ..., a_(t+H-1)]이며, π0는 H = 50을 사용한다. Action chunking은 ACT 논문에서 제안된 개념이다.
쉽게 다시 말하면
한 스텝의 동작이 아니라, 미래 50개 스텝의 연속 동작을 한 번에 만들어낸다.
각각 따로따로 뚝뚝 끊긴 명령이 아니라, 하나의 이어진 흐름(방향성을 가진 연속 동작)으로 추론한다.
6-2. 왜 청크로 만드는가
전문 설명
매 timestep마다 독립적으로 추론하면 인접 스텝 간 예측이 불일치하여 jittery motion이 발생한다. 청크 단위 예측은 chunk 내부의 temporal consistency를 보장한다.
쉽게 다시 말하면
중요한 구분: 액션 청크가 compounding error를 해결하는 것은 아니다
| 매 순간 추론이 오락가락해서 동작이 떨림 | 매 스텝 독립 추론 | 액션 청크 (해결됨) |
| 실행 후 현실이 달라져 오차가 누적됨 | 학습 때 못 본 상태로 재진입 | 청크로는 막지 못함 |
문제 원인 해결책
7. [블록 6] 로봇 실행
7-1. 기능과 실제 추론 시간
전문 설명
생성된 50스텝 액션 청크를 로봇의 관절 명령으로 변환하여 순차 실행한다. π0는 최대 50Hz의 제어 주파수를 지원한다.
논문 Appendix D, Table 1 기준: GeForce RTX GPU에서 73ms의 추론 시간으로, 3개 카메라 입력을 처리하고 50개 액션 청크를 생성한다.
재구현체 실측 (RTX 4090):
| float32 | 237ms | 13.6GB |
| bf16 | 245ms | 6.7GB |
| float32 + torch.compile | 89ms | 13.6GB |
| bf16 + torch.compile | 75ms | 6.7GB |
| 논문 수치 | 73ms | - |
설정 시간 Peak VRAM
torch.compile 최적화를 적용해야 논문 수준의 속도에 근접한다는 점이 실무적으로 중요하다.
7-2. 실행 속도와 청크 길이의 관계 청크가 담당하는 실제 시간 = 청크 개수(50) / 실행 속도(Hz)
| 50Hz | 1초 |
| 20Hz | 2.5초 |
| 10Hz | 5초 |
실행 속도 50스텝 청크 = 몇 초?
실행 속도는 성능에 영향을 준다
"속도만 바뀌고 성능은 그대로"가 아니다.
7-3. π0는 동기식(synchronous) 실행이다
중요한 사실 (Physical Intelligence 공식 자료에서 확인)
π0, π0-FAST, π0.5는 모두 real-time 전략을 사용하지 않고, 액션을 동기적으로 실행했다. 즉 한 청크 실행을 다 끝내고, 모델 추론을 기다린 다음, 다음 청크를 실행하는 방식이다.
이는 SmolVLA의 비동기 추론(asynchronous inference)과 대비되는 지점이다.
PI는 이후 RTC(Real-Time Chunking)라는 별도 알고리즘을 개발해서 이 문제를 해결했으나, 이는 π0 원 논문에는 없는 후속 연구다.
8. [블록 7] 재입력 - Compounding Error가 발생하는 지점
8-1. 무슨 일이 일어나는가
전문 설명
로봇 실행 후 변화한 proprioceptive state와 시각 관측이 다음 timestep의 관측 o_(t+1)로 재입력된다. 정책의 출력에 미세한 오차가 있으면, 그 오차가 반영된 state가 다시 입력이 되어 covariate shift를 일으키고, 이것이 스텝을 거듭하며 누적된다. 이를 compounding error라 한다.
쉽게 다시 말하면
출력일 때는 작은 오차가 큰 문제가 안 되는데, 그것이 다시 입력으로 들어가니까 오차가 커진다.
메커니즘:
8-2. π0는 이것을 어떻게 완화하는가
완전히 "해결"되지는 않는다. 논문도 이를 완전히 해결했다고 주장하지 않는다.
완화 전략 1: Pre-training에 "실수 + 회복" 데이터를 일부러 포함
논문은 pre-training 데이터의 다양성(그리고 상대적으로 낮은 품질)이 recovery behavior를 학습하는 데 필수적이라고 명시한다. 고품질 데이터만으로 학습하면 실수 상황이 거의 없어 회복 전략을 배우지 못한다.
이것이 직관과 반대되는 핵심 통찰이다.
운전 배우기 비유:
완화 전략 2: Post-training으로 정교함 추가
Pre-training(회복력) + Post-training(정교한 실행)을 조합한다.
완화 전략 3: 액션 청크로 일관성 유지
매 순간 추론 불일치는 줄여준다 (다만 재입력 오차 자체는 막지 못함).
9. π0 학습 파이프라인 - Pre-training과 Post-training
9-1. Pre-training
| 총 데이터 규모 | 10,000시간 이상의 로봇 데이터 |
| 자체 수집 데이터 | 903M timesteps (single-arm 106M, dual-arm 797M) |
| 로봇 종류 | 7가지 구성 |
| Task 수 | 68개 |
| 오픈소스 비중 | 9.1% (OXE, Bridge v2, DROID) |
| 학습 스텝 | 700k steps |
| 샘플 균형 보정 | task-robot 조합별로 n^0.43 가중치 |
항목 내용
7가지 로봇 구성 (SO-101은 여기 없다)
쉽게 다시 말하면
"이 로봇 저 로봇 다 섞어서 폭넓게 배우는 단계." 목표는 잘하는 것이 아니라 넓게 아는 것이다.
9-2. Post-training (Fine-tuning)
전문 설명
특정 downstream task에 특화시키기 위해 소규모 고품질 데이터로 fine-tuning한다. 가장 단순한 task는 5시간, 가장 복잡한 task는 100시간 이상의 데이터를 사용한다.
openpi 코드에서 확인된 두 가지 모드
| Full fine-tuning | Pi0Config() (기본값) | 전체 파라미터 학습 |
| LoRA fine-tuning | Pi0Config(paligemma_variant="gemma_2b_lora", action_expert_variant="gemma_300m_lora") | 대부분 freeze, LoRA 어댑터만 학습 (저메모리) |
모드 설정 특징
get_freeze_filter() 함수가 파라미터 이름 패턴으로 freeze 대상을 결정한다:
쉽게 다시 말하면
"이제 특정 작업 하나를 진짜 잘하도록 집중 훈련하는 단계."
9-3. 평가 방법 (Appendix E)
평가 지표는 작업당, 방법당 10회 에피소드에 걸쳐 평균낸 정규화 점수를 사용한다.
10. Cross-embodiment training과 Pre/Post-training - 헷갈리지 말 것
이 둘은 서로 다른 축(axis)의 개념이다.
| 무엇에 대한 얘기? | 무엇을 섞어서 학습하는가 (데이터의 종류) | 언제, 어떤 목적으로 학습하는가 (학습의 단계) |
| 내용 | 여러 로봇(embodiment)의 데이터를 한 모델에 섞음 | 범용 학습 → 특화 학습의 2단계 구성 |
| 비유 | 어떤 재료를 섞어 요리하나 | 언제 기초를 배우고 언제 응용을 배우나 |
Cross-embodiment training Pre-training / Post-training
관계: Cross-embodiment training은 pre-training 단계에서 쓰이는 전략이다.
11. π0 vs SmolVLA - 구조적 차이 5가지
| 1 | Action expert의 attention | Self-attention 공유 + FFN 분리 (MoE 방식) | Cross-attention과 self-attention을 번갈아 배치 | 효율화 + 표준 재구성 |
| 2 | VLM 레이어 활용 | 마지막 레이어까지 전부 사용 | 중간 레이어(N=L/2)에서 추출, 나머지는 계산 생략 (layer skipping) | 순수 효율화 |
| 3 | 이미지 토큰화 | 표준 방식 (압축 단계 없음) | PixelShuffle로 프레임당 64토큰까지 압축 | 순수 효율화 |
| 4 | 추론 실행 | 동기식(synchronous) | 비동기 추론 (실행과 판단을 분리) | 순수 효율화 |
| 5 | Pre-training 데이터 | 자체 수집 (회사가 직접) | 커뮤니티 공개 데이터 (HuggingFace Hub) | 전략/철학 차이 |
# 항목 π0 SmolVLA 성격
핵심 결론
1~4번은 "π0의 기본 뼈대는 그대로 두고, 계산을 더 가볍고 빠르게 하는 최적화"다. 5번만이 최적화가 아니라, "누구나 접근 가능한 오픈소스 생태계를 만들겠다"는 근본 목표의 차이다.
단, "π0의 아키텍처를 쓰려면 반드시 자체 수집 데이터만 써야 한다"는 규칙은 없다. 이것은 두 프로젝트가 실제로 택한 데이터 소싱 방법의 차이일 뿐이다.
12. π0-small - VLM 사전학습 효과를 검증하기 위한 비교 모델
12-1. 왜 존재하는가
π0-small은 "VLM 사전학습이 정말 도움이 되는가"를 검증하기 위한 ablation(비교 실험)용 모델이다. 470M 파라미터이고 VLM 초기화를 사용하지 않는다.
12-2. π0 본체와의 구체적 차이 (Appendix C)
| 언어 처리 | Gemma (VLM 백본의 일부) | DistilBERT |
| 이미지 인코딩 | SigLIP (PaliGemma 내장) | R26-S-32 ResNet-ViT 하이브리드 |
| Action expert 연결 방식 | Decoder-only MoE (self-attention 공유) | 전통적 encoder-decoder (cross-attention) |
| Action expert 아키텍처 | Gemma | DiT (Diffusion Transformer) |
| Timestep 주입 방식 | 토큰으로 시퀀스에 포함 | AdaLN-Zero 레이어 |
| 관측 인코딩 백본 | 인터넷 데이터로 사전학습됨 | 사전학습 안 됨 |
항목 π0 본체 π0-small
공통점: 둘 다 사전학습된 ViT 이미지 인코더를 쓰고, 관측 인코더와 action expert에 별도 가중치를 쓰며, 같은 관측을 받고, 10 스텝 flow matching으로 액션 청크를 예측한다.
12-3. 이 비교의 한계
π0-small은 파라미터 수도 더 적어서, 이 비교를 완전히 공정하게 만들기는 어렵다고 저자들이 직접 인정한다.
즉 성능 차이가 나더라도 그것이:
완벽히 분리해내지 못했다. 엄밀한 증명이라기보다 대략적인 경향을 보여주는 참고 실험으로 이해해야 한다.
12-4. 참고: Timestep 주입 방식의 차이 (AdaLN-Zero)
AdaLN(Adaptive Layer Norm)이란: layer normalization의 scale(γ)과 shift(β) 파라미터를 고정된 값으로 두지 않고, timestep을 입력받는 작은 신경망이 매번 새로 계산해내는 방식이다.
AdaLN-Zero는 여기에 추가로, 학습 시작 시 조정 효과가 0에서 시작하도록 초기화하는 안정화 기법이다.
DiT 원 논문에서 네 가지 방식(in-context 토큰, cross-attention, AdaLN, AdaLN-Zero)을 비교한 결과, DiT 아키텍처 안에서는 AdaLN-Zero가 가장 좋은 성능을 보였다.
다만 이것이 "Gemma가 성능이 나쁘다"는 뜻은 아니다. Gemma는 애초에 언어모델용 구조라 AdaLN-Zero 같은 diffusion 전용 장치가 내장되어 있지 않으며, π0가 Gemma를 쓰는 이유는 인터넷 규모로 학습된 언어 이해 능력을 통째로 상속받기 위해서다. 두 모델은 애초에 다른 목적으로 선택된 것이다.
13. 기술과 블록도 위치 총정리
| SigLIP (ViT) | 블록 1 (입력) | 이미지를 패치 토큰으로 변환 |
| 텍스트 토크나이저 | 블록 1 (입력) | 언어를 토큰으로 변환 |
| Linear projection (MLP) | 블록 1 (입력) | state를 언어 토큰과 같은 차원으로 투영 |
| Zero-padding | 블록 1 (입력) | 로봇마다 다른 state/action 차원을 18차원으로 통일 |
| Image masking | 블록 1 (입력) | 카메라 3개 미만인 로봇의 빈 슬롯 처리 |
| Self-attention | 블록 2, 3 | 토큰 간 연관도 계산 및 정보 교환 (두 expert가 공유) |
| FFN (feed-forward) | 블록 2, 3 | 섞인 정보 중 중요한 조합 선별 (expert별로 분리) |
| Residual connection | 블록 2, 3 | 원본 정보 유실 방지 (변화량만 계산해 더함) |
| Mixture of Experts (MoE) | 블록 3 (action expert) | 이미지/언어용 가중치(llm_0)와 로봇용 가중치(llm_1) 분리 |
| Bidirectional mask | 블록 3 (prefix 부분) | 이미지/언어 토큰끼리는 자유롭게 참조 |
| Causal mask | 블록 3 (suffix 부분) | 액션 토큰은 앞선 액션만 참조 (미래 정보 차단) |
| Sine-cosine timestep 임베딩 | 블록 3 (action expert) | flow matching 스텝 번호를 토큰으로 변환 |
| Flow matching | 블록 4 | 노이즈에서 액션으로의 벡터장 학습 및 적분 |
| Forward Euler 적분 | 블록 4 | 10 스텝으로 벡터장을 따라 이동 |
| Beta(1.5, 1) 샘플링 | 블록 4 (학습 시) | 노이즈가 많은 구간을 집중적으로 학습 |
| KV 캐싱 | 블록 4 (추론 시) | prefix의 attention 결과 재사용, 속도 개선 |
| Action chunking | 블록 5 | 미래 50스텝을 한 번에 예측 (temporal consistency) |
| Cross-embodiment training | 학습 파이프라인 (pre-training) | 여러 로봇 데이터를 한 모델에 통합 |
| LoRA | 학습 파이프라인 (post-training) | 저메모리 fine-tuning |
| High-level VLM policy | 블록 1 외부 (선택적) | 큰 지시를 세부 지시로 분해 (SayCan 유사) |
기술 어느 블록에서 쓰이나 역할
14. SO-101에 π0를 적용할 때 - 실무적 시사점
14-1. 제로샷은 왜 어려운가
근거 1 - 논문
π0의 pre-training에 쓰인 7가지 로봇 목록에 SO-101/SO-100 계열이 없다.
근거 2 - openpi 공식 README (직접 증거)
제공되는 expert 체크포인트들은 ALOHA와 DROID Franka 설정처럼 더 널리 쓰이는 로봇으로 수집된 비교적 작은 데이터셋에서 fine-tuning된 것이라, 사용자의 특정 로봇 설정에는 일반화되지 않을 수 있다고 명시한다.
또한 π0는 자체 로봇용으로 개발됐고 ALOHA/DROID 같은 널리 쓰이는 플랫폼과도 다르며, 다른 플랫폼에 적용하는 실험을 시도할 수는 있지만 모든 시도가 성공할 거라 기대하지는 않는다고 개발사가 직접 밝히고 있다.
근거 3 - 코드 레벨 확인
openpi의 config.py에 있는 실제 fine-tuning 예시들(ALOHA, DROID, LIBERO, Trossen)에 SO-101 관련 설정이 전혀 없다.
근거 4 - 제로 패딩의 한계
제로 패딩은 형식만 맞출 뿐, 관절 구조의 의미까지 자동 매칭해주지 않는다 (2-4장 참조).
14-2. Fine-tuning 데이터를 어떻게 구성할 것인가
핵심 원칙
SO-101 자체가 pre-training에 없던 로봇이므로, pre-training에서 얻은 "회복력"의 혜택을 온전히 받지 못할 수 있다. 따라서 fine-tuning 데이터 자체의 다양성이 더 중요해진다.
권장 구성
14-3. 실무 팁
추론 속도가 논문의 73ms에 근접하려면 torch.compile 최적화가 필수적이다. 최적화 없이는 200ms 이상 걸릴 수 있다 (7-1장 표 참조).
15. 한 줄 요약
π0는 인터넷 규모로 학습된 VLM(PaliGemma)이 "무엇을 봐야 하고 무엇을 하라고 했는지"를 이해하고, 별도의 가중치를 가진 action expert가 그 이해를 조건으로 삼아, 랜덤 노이즈에서 출발해 flow matching으로 10번 이동하며 50스텝의 연속 동작을 만들어내는 모델이다.
작성일: 2026-07-13
기반 자료:
|
|
첫댓글 정리를 너무 잘했어요
ACT와 VLA모델에서 action decoder로 각각 사용되고 있는 VAE(variational autoencoder,변분오토인코더)와 Diffusion model(확산모델)도 공부해보세요 2개 모두 생성형 모델입니다.