|
|
GR00T N1 뜯어보기 — 휴머노이드 로봇을 위한 오픈 파운데이션 VLA 모델
GR00T N1구조도(다이어그램)
이 글은 NVIDIA GEAR 팀의 GR00T N1(arXiv 2503.14734) 논문을 구조 중심으로 정리한 글입니다. π0, SmolVLA를 공부한 흐름의 연장선에서, "이 모델이 어떻게 생겼고(본론), 무엇을 먹고 자랐는지(사전지식: 데이터 피라미드)"를 순서대로 다룹니다. 각 개념은 전문적인 설명 → 직관적인 재설명 순서로 두 번씩 짚습니다.
이 글의 구성
GR00T N1을 이해하려면 두 가지를 알아야 합니다. 첫째, 모델이 어떻게 생겼는가(아키텍처). 둘째, 그 모델을 무슨 데이터로 어떻게 학습시켰는가(데이터 파이프라인). 그런데 두 번째, 특히 "데이터 피라미드"를 모르면 첫 번째의 설계 이유가 잘 와닿지 않습니다. 그래서 이 글은 데이터 피라미드를 먼저 사전 지식으로 독립되게 다룬 뒤, 본론인 모델 구조로 들어갑니다.
사전 지식 — 데이터 피라미드 (Data Pyramid) 왜 이게 먼저 나와야 하는가
로봇 학습에는 근본적인 문제가 하나 있습니다. 텍스트나 이미지는 인터넷에 무한히 널려 있지만, 로봇 데이터는 그렇지 않다는 것입니다. 특정 로봇 하드웨어 하나에 대한 데이터는 언제나 턱없이 부족합니다.
직관적으로: 유튜브엔 고양이 영상이 수억 개 있지만, "SO-101 로봇팔이 컵을 집는 영상"은 누군가 직접 로봇을 조작해서 찍지 않는 한 존재하지 않습니다. 로봇 데이터는 '희귀템'입니다. 이 희귀한 데이터를 어떻게 최대한 불려서 쓸 것인가 — 이것이 데이터 피라미드가 답하려는 질문입니다.
데이터 피라미드란 무엇인가
전문적으로: 데이터 피라미드는 서로 이질적인(heterogeneous) 데이터 출처들을 **데이터 양(quantity)**과 **로봇 특화도(embodiment-specificity)**라는 두 축으로 계층화한 프레임워크입니다. 위로 갈수록 양은 적어지고 특화도는 높아집니다. GR00T N1이 처음 제안한 개념이며, 이후 연구들도 "GR00T N1이 도입했다"고 인용합니다.
직관적으로: 데이터를 "얼마나 많은지"와 "얼마나 그 로봇 전용인지"에 따라 삼각형으로 쌓아놓은 지도입니다. 아래는 양이 많고 범용적, 위는 양이 적고 전용입니다.
🖼️ [그림: 데이터 피라미드 삼각형] — 3층 삼각형. 맨 아래(넓음)부터 위로 기반층(웹데이터 + 인간 1인칭 비디오), 중간층(시뮬레이션 궤적 + Neural Trajectory), 정점층(실제 로봇 원격조작 데이터). 오른쪽에 세로 화살표 "데이터 양: 아래로 갈수록 많음", 왼쪽에 "로봇 특화도: 위로 갈수록 높음"을 표기.
한 가지 중요한 오해를 먼저 막아야 합니다. 이 피라미드는 데이터의 **포맷(형태)**을 나눈 것이 아닙니다. 세 층의 데이터는 최종적으로 전부 같은 형태, 즉 "입력 = 로봇 상태 + 시각 정보 + 언어 지시 → 출력 = 모터 액션"으로 통일됩니다. 층을 가르는 기준은 오직 양과 특화도입니다.
핵심 원리: 원래 액션 라벨이 얼마나 있느냐에 따라 필요한 전처리가 달라진다
각 층은 "GR00T가 학습에 쓸 수 있는 형태(액션 라벨이 붙은 형태)"로 만들기까지 필요한 손질의 양이 다릅니다.
| 층 | 원래 상태 | 필요한 전처리 |
| 정점층 (실제 로봇) | 진짜 액션 라벨이 이미 있음 | 거의 없음 (형식 정돈만) |
| 중간층 (시뮬레이션) | 시뮬레이터가 액션값을 계산해 이미 있음 | 거의 없음 |
| 중간층 (Neural Trajectory) | 생성된 영상이라 액션 라벨 없음 | IDM으로 라벨링 |
| 기반층 (웹/인간 비디오) | 액션 라벨이 아예 없음 | Latent Actions로 라벨링 |
직관적으로: 위층 데이터는 "정답지가 딸려 있는 문제집"이라 그냥 풀면 되고, 아래층 데이터는 "정답이 없는 문제집"이라 누군가 정답을 만들어 붙여줘야 씁니다. 그 '정답 만들기' 기술이 Latent Actions와 IDM입니다.
🖼️ [그림: 데이터 피라미드 3층 × 라벨링 기법 매핑] — 그림1의 피라미드 삼각형 옆에, 각 층에서 화살표로 연결되는 라벨링 기법 박스. 정점층 → "전처리 거의 없음", 중간층(시뮬레이션) → "전처리 거의 없음", 중간층(Neural Trajectory) → "IDM", 기반층 → "Latent Actions(VQ-VAE)". 화살표 굵기나 색으로 "전처리 필요 정도"를 위(얇음/없음)에서 아래(굵음/많음)로 표현.
정점층 (Peak) — 실제 로봇 원격조작 데이터
전문적으로: 사람이 로봇을 원격조작(teleoperation)하여 수집한 실제 궤적 데이터입니다. 관절 인코더 등 센서가 "로봇 상태 + 실제 액션"을 그대로 기록하므로 ground-truth 액션 라벨이 처음부터 존재합니다. 양은 가장 적지만(사람이 직접 조작해야 하므로) 특정 로봇에 대한 신뢰도는 가장 높습니다.
직관적으로: 사람이 진짜 로봇을 직접 움직여서 얻은 "진짜배기 데이터"입니다. 만들기 느리고 비싸지만 가장 정확합니다. 정답이 이미 다 적혀 있어서 별도 손질이 필요 없습니다.
중간층 (Middle) — 두 가지 서로 다른 재료
중간층은 하나가 아니라 두 종류의 데이터로 이루어집니다. 이 둘은 서로 보정하는 관계가 아니라, 각자 독립적으로 "진짜 로봇 데이터를 흉내내는" 병렬적인 두 경로입니다.
(1) 시뮬레이션 궤적
전문적으로: Isaac Sim 같은 물리 엔진으로 생성한 궤적입니다. 시뮬레이터가 물리 법칙을 계산하므로 액션값이 내장되어 있습니다. 다만 실제 물리 세계의 근사치이므로 sim-to-real gap이 존재하여 정점층이 아닌 중간층에 위치합니다.
직관적으로: 컴퓨터 게임 속 물리 엔진으로 만든 로봇 동작입니다. 빠르게 대량으로 찍어낼 수 있지만, 진짜 세상과 미세하게 달라서 "완벽한 진짜"는 아닙니다.
여기서 짚을 것이 있습니다. 관절값이 "있다/없다"가 층을 나누는 기준이 아닙니다. 시뮬레이션도 관절값이 있습니다. 정점층과의 차이는 그 값이 진짜 물리 세계에서 나왔는지(정점), 컴퓨터가 근사 계산한 것인지(중간)입니다.
(2) Neural Trajectory
블록도 상 위치: 모델 블록도 내부가 아니라 학습 데이터를 준비하는 단계(중간층)입니다. GR00T N1의 추론 파이프라인에는 등장하지 않고, 학습 데이터셋을 만드는 별도 과정입니다.
전문적으로: 실제 로봇 영상으로 파인튜닝한 image-to-video 생성 모델에, "시작 프레임 + 새로운 언어 지시"를 입력하여 생성한 반사실적(counterfactual) 로봇 영상입니다. N1에서는 이 방식으로 해당 계층 데이터를 88시간에서 827시간까지 증폭했습니다.
직관적으로: "사진 한 장 + 텍스트를 주면 다음 영상을 상상해서 만들어주는 AI"(원래는 고양이가 움직이는 영상 같은 걸 만들던 범용 모델)에
게, 특정 로봇 영상을 잔뜩 보여줘서 "이 로봇은 이런 식으로 움직이는구나"를 익히게 한 뒤, 실제로 해본 적 없는 새 지시("컵을 왼쪽으로 옮겨")를 줘서 그럴듯한 가짜 영상을 만들어내게 하는 것입니다.
여기서 중요한 오해를 막아야 합니다. 이 생성 모델은 관절이나 구동부 같은 기계적 정보를 명시적으로 이해하지 않습니다. 오직 "픽셀이 어떻게 변하는가"라는 시각적 패턴만 배웁니다. 사람이 해부학을 몰라도 "팔을 뻗는 다음 자세"를 그럴듯하게 그릴 수 있는 것과 같습니다. 그래서 만들어진 영상엔 액션 라벨(관절값)이 없고, 이후 IDM으로 라벨을 붙여야 합니다.
시뮬레이션이 있는데 왜 Neural Trajectory까지 쓰는가
전문적으로: 물리 시뮬레이터는 rigid body(딱딱한 물체) 조작은 잘 다루지만, 변형 물체(천 접기), 접촉이 많은 도구 사용(망치질), 액체 같은 작업은 물리 계산 자체가 극도로 어렵거나 부정확합니다. Neural Trajectory는 물리를 계산하는 대신 시각적 외형을 흉내내므로, 시뮬레이터가 손대기 어려운 이런 영역을 정밀도는 다소 낮더라도 메울 수 있습니다.
직관적으로: 시뮬레이터는 "계산으로 예측"하고, Neural Trajectory는 "그림 실력으로 상상"합니다. 천이 어떻게 구겨지는지는 계산하기 너무 어렵지만, "천이 접힐 때 대충 이렇게 보이더라"는 흉내낼 수 있습니다. 그래서 둘은 경쟁이 아니라 서로의 약점을 메우는 상호보완 관계입니다.
기반층 (Base) — 웹데이터 + 인간 비디오, 그리고 Latent Actions
전문적으로: 웹 스케일 데이터와 인간 1인칭(egocentric) 비디오로 구성된, 양이 가장 많고 로봇 특화도가 가장 낮은 층입니다. 이 데이터에는 액션 라벨이 아예 없으므로 Latent Actions(VQ-VAE 기반)로 pseudo-action 라벨을 생성합니다.
직관적으로: 인터넷에 넘쳐나는 영상과 사람이 뭔가 하는 1인칭 영상들입니다. 로봇 관절값 같은 건 당연히 없습니다(사람이니까요). 그래서 "가짜 정답"을 만들어 붙여야 하는데, 그 도구가 Latent Actions입니다.
Latent Actions (VQ-VAE) — 어떻게 구현되는가
블록도 상 위치: 모델 블록도 내부가 아니라 학습 데이터 준비 단계(기반층 라벨링 도구)입니다. 학습이 끝난 뒤 인코더만 남아, GR00T N1의 Action Encoder에 넣을 pseudo-action 값을 만드는 데 쓰입니다.
🖼️ [그림: Latent Actions 인코더/디코더 흐름] — 왼쪽에서 오른쪽으로 [두 프레임] → [인코더] → [코드(숫자)] → [디코더] → [복원된 프레임] → [원본과 비교 = 오차], 그리고 그 오차가 인코더/디코더로 되돌아가는 역전파 화살표. 학습 후 디코더는 회색 처리(버려짐), 인코더만 강조.
전문적으로: 인코더-디코더 구조의 VQ-VAE입니다. 인코더는 연속된 두 프레임 $(x_t, x_{t+H})$을 입력받아 코드북에서 이산적인 latent action $z_t$를 출력합니다. 디코더는 (그 코드 + 첫 프레임)으로 두 번째 프레임을 복원합니다. 학습은 복원 오차를 역전파로 줄이며 인코더와 디코더를 함께 최적화하는 방식입니다. 학습이 끝나면 디코더는 버리고, 인코더만 inverse dynamics처럼 재사용하여 pseudo-action 라벨을 추출합니다.
직관적으로: 동영상 압축(코덱)과 같은 발상입니다. 인코더는 "두 장면 사이의 변화량"을 숫자(코드)로 압축하고, 디코더는 그 숫자로 원래 장면을 복원해보며 "이 숫자가 쓸만한지" 채점합니다. 채점(복원)이 잘 될수록 좋은 코드라는 뜻이므로, 이렇게 인코더와 디코더를 짝지어 훈련합니다. 훈련이 끝나면 채점자(디코더)는 버리고, 압축기(인코더)만 남겨서 실제 라벨링에 씁니다. 인코더 혼자서는 자기가 뽑은 숫자가 좋은지 알 수 없기 때문에, 디코더가 그 검증 역할을 해주는 짝꿍인 셈입니다.
이 코드를 실제로 어떻게 쓰는가
전문적으로: 추출된 latent action(양자화 이전의 연속 임베딩)을 pseudo-action 라벨로 삼아, 이 데이터를 "LAPA"라는 별도의 embodiment로 취급합니다. 그리고 진짜 로봇 데이터와 동일한 flow-matching 손실로 GR00T N1을 학습시킵니다. 모델 입장에서는 손실 함수의 정답($A_t$) 자리에 진짜 관절값 대신 latent action 임베딩이 들어갈 뿐, 학습 절차 자체는 완전히 동일합니다.
직관적으로: "이 상황(이미지+언어)에서는 이 코드가 정답이다"라는 짝을 GR00T에게 반복 학습시킵니다. GR00T는 그 코드가 "무슨 뜻인지"는 몰라도, "이런 상황엔 이런 코드"라는 패턴만 익히면 됩니다. 마치 외국어 뜻은 몰라도 "이 상황엔 이 단어가 나오더라"를 익히는 것과 같습니다.
그래서 Latent Actions로 실제로 배우는 것은
전문적으로: latent action은 진짜 관절값과 물리적 상관이 없는 추상적 코드입니다. 따라서 이 데이터의 실질적 기여는 정밀한 모터 제어가 아니라, 다양한 시각-언어 상황을 접하게 함으로써 System 2(VLM)의 상황 이해 능력을 넓히는 것에 가깝습니다. 정밀 제어 능력은 진짜 로봇 데이터가 전담합니다. 다시 말해 GR00T는 진짜 로봇 데이터에서는 "상황 ↔ 정확한 관절값"을, LAPA 데이터에서는 "상황 ↔ 대략적 반응 코드"를 배우며, 같은 신경망 안에서 이 둘이 태그로 구분된 채 서로 다른 역할로 기여합니다.
직관적으로: 인간 비디오는 "정확히 어떻게 움직여라"를 가르치는 게 아니라, "이 장면을 보면 대충 뭘 하려는 상황이구나"라는 판단력·이해력을 키워줍니다. 외국어를 하나도 몰라도 그 나라 드라마를 많이 보면 "대화의 흐름과 분위기"는 익힐 수 있는 것처럼요. "실행"은 진짜 로봇 데이터가, "이해"는 이런 다양한 데이터가 담당하는 역할 분담입니다.
⚠️ 정직한 한계: Latent Actions(VQ-VAE)는 완성된 이론이 아닙니다. 최근 연구들은 이 방식이 진짜 동작이 아닌 겉모습 단서에 의존하는 shortcut learning, 그리고 카메라 흔들림 같은 무관한 외부 노이즈까지 코드에 섞는 문제를 지적합니다. 즉 2D 영상에서 애매한 동작(옆에서 본 왼팔/오른팔 흔들기 등)을 완벽히 구분하지 못할 수 있습니다. "왜 이게 도움이 되는가"에 대한 완전한 이론적 설명은 아직 없으며, 경험적으로 도움이 된다는 것이 실험으로 확인된 상태입니다(뒤 성능 수치 참고).
두 라벨링 기법 비교 — Latent Actions vs IDM
블록도 상 위치: 둘 다 모델 블록도 밖, 학습 데이터 준비 단계입니다. Latent Actions는 기반층, IDM은 중간층(Neural Trajectory) 라벨링에 쓰입니다.
중간층 Neural Trajectory에도 라벨이 필요한데, 여기엔 주로 IDM(Inverse Dynamics Model)을 씁니다. 두 기법을 정리하면 다음과 같습니다.
| 학습에 진짜 (영상,액션) 데이터 필요? | 필요 없음 | 필요 (그 로봇 전용) |
| 사람 영상에도 적용 가능? | 가능 | 어려움 |
| 결과물 형태 | 추상적 코드 | 실제 관절값에 가까운 추정치 |
| 주로 쓰이는 층 | 기반층 (인간 비디오) | 중간층 (Neural Trajectory) |
| 데이터 양과의 관계 | 무관 (일정) | 데이터 많을수록 정밀해짐 |
Latent Actions (LAPA) IDM
전문적으로: IDM은 대상 로봇의 실제 (영상, 액션) 쌍으로 사전 학습된 embodiment-specific 모델입니다. Neural Trajectory는 그 로봇 영상으로 파인튜닝된 생성 모델의 산출물이므로 이미 해당 로봇에 특화되어 있어, 같은 로봇에 특화된 IDM과 궁합이 좋습니다. 반면 LAPA는 여러 embodiment에 걸쳐 범용으로 학습되어, 로봇이 아닌 인간 비디오처럼 특화가 불가능한 데이터에 적합합니다. IDM은 반드시 사전에 학습이 완료된 상태여야 이후 단계에서 라벨러로 투입될 수 있습니다.
직관적으로: "그 로봇 전용으로 만든 영상(Neural Trajectory)"에는 "그 로봇 전용 라벨러(IDM)"가 잘 맞고, "아무 영상에나 통하는 범용 라벨러(LAPA)"는 사람 영상처럼 특화가 불가능한 데이터에 씁니다. 전용 도구는 전용끼리, 범용 도구는 범용이 필요한 곳에 씁니다.
"순환 논리 아닌가"에 대한 답: IDM을 학습시키려면 진짜 데이터가 필요한데, 그게 있으면 이미 문제가 해결된 것 아니냐고 볼 수 있습니다. 하지만 이건 증폭 구조입니다. 소량의 진짜 데이터(예: 전체의 10%)로 IDM과 생성 모델을 학습시키고, 그 도구들로 훨씬 많은 가짜 데이터를 만들어냅니다. 10장의 사진으로 화풍을 배운 화가가 100장을 그려내는 것과 같습니다. 재료(진짜 데이터)는 적고, 결과물(가짜 학습 데이터)은 많습니다.
실험 결과 (Sec 4.4)
전문적으로: Neural Trajectory co-training을 추가하면 성공률이 시뮬레이션 기준 +4.2%(30 demos) / +8.8%(100) / +6.8%(300), 실제 로봇 기준 평균 +5.8% 향상됩니다. 저데이터(30 demos)에서는 LAPA가 IDM보다 근소 우세하나, 데이터가 늘수록 IDM이 역전합니다. 이는 IDM 학습 데이터가 많을수록 pseudo-action이 실제 액션에 근접하기 때문입니다. 실제 로봇(GR-1)에는 IDM만 사용하는데, GR-1이 상대적으로 "데이터가 많은" 환경이라 IDM이 유리하기 때문입니다.
직관적으로: 가짜 데이터를 섞는 게 단순 땜빵이 아니라 실제로 4~9% 성능을 올립니다. 데이터가 적을 땐 LAPA가 살짝 낫지만(IDM이 재료 부족으로 부정확해서일 뿐, LAPA가 특별히 좋아진 게 아닙니다), 데이터가 많아지면 IDM이 앞섭니다. LAPA는 로봇 데이터 양과 무관하게 일정한 반면, IDM은 데이터가 늘수록 계속 좋아지기 때문입니다.
세 층을 어떻게 섞어서 학습하는가
전문적으로: 세 층을 순차적 커리큘럼이 아니라, 매 학습 배치마다 세 층에서 함께 샘플링하여 end-to-end로 동시 사전학습합니다. Post-training 단계에서는 실제 궤적과 Neural Trajectory를 1:1 비율로 co-training합니다.
직관적으로: "먼저 인간 비디오, 그다음 시뮬레이션, 마지막에 로봇" 순서로 배우는 게 아니라, 매 순간 세 층을 골고루 섞어서 한꺼번에 배웁니다.
본론 — GR00T N1 모델 구조
이제 위 데이터로 학습되는 모델 자체를 봅니다.
🖼️ [그림: 전체 블록도] — 이 글의 대표 구조도. 상단에 입력 4개(이미지+언어 지시 / 로봇 상태 / 노이즈 액션), 좌측에 System 2(Eagle-2 VLM: SigLIP-2 + SmolLM2), 우측 하단에 System 1(DiT: DiT 블록 → 액션 디코더). 입력과 System 1 사이에 State/Action Encoder(로봇별 전용 MLP)를 배치하고, Action Decoder 출력이 노이즈 액션 자리로 되돌아가는 되먹임 화살표("System 1 전체를 4번 반복")와 최종 출력("최종 동작 명령")을 포함.
전문적으로: GR00T N1은 dual-system 구조의 VLA(Vision-Language-Action) 모델입니다. 총 2.2B 파라미터이며, System 2(VLM)가 1.34B를 차지합니다. System 2는 Vision-Language 모듈로 이해를 담당하는 느린 시스템이고, System 1은 Diffusion Transformer로 실행을 담당하는 빠른 시스템입니다. 이 dual-system 발상 자체는 π0에서 본 "VLM + action expert" 구도와 같은 계열이지만, GR00T는 두 시스템을 명시적으로 분리했다는 점이 특징입니다.
직관적으로: 두 개의 뇌를 가진 로봇입니다. 하나(System 2)는 "지금 상황이 뭐고 뭘 해야 하는지" 천천히 이해하는 뇌, 다른 하나(System 1)는 "그럼 몸을 어떻게 움직일지" 빠르게 계산하는 뇌입니다.
🖼️ [그림: 입력 4가지 분류도] — 상단에 입력 4개 박스를 나란히(이미지 / 언어 지시 / 로봇 상태 / 노이즈 액션), 왼쪽 2개(이미지, 언어 지시)에서 아래로 화살표가 모여 "System 2"로, 오른쪽 2개(로봇 상태, 노이즈 액션)에서 아래로 화살표가 모여 "System 1"로 향하는 두 갈래 갈림길 형태.
전문적으로: 모델의 입력은 4가지이며, 목적지에 따라 2+2로 나뉩니다.
| 입력 | 인코딩 경로 | 목적지 |
| 이미지 (224×224) | SigLIP-2 → pixel shuffle → 64토큰 | System 2 |
| 언어 지시 | 텍스트 토크나이저 | System 2 |
| 로봇 상태 (관절 각도) | State Encoder (로봇별 전용 MLP) | System 1 |
| 노이즈 액션 (가우시안, 청크 H=16) | Action Encoder (로봇별 전용 MLP) | System 1 |
이미지와 언어는 "이해 담당"인 System 2로 가고, 로봇 상태와 노이즈 액션은 "실행 담당"인 System 1으로 갑니다. 노이즈 액션은 처음엔 순수 랜덤값이며, 이것이 나중에 실제 동작으로 채워질 "빈 그릇" 역할을 합니다.
직관적으로: "눈에 보이는 것(이미지)"과 "들은 지시(언어)"는 이해하는 뇌로, "지금 내 몸 상태(로봇 상태)"와 "채워나갈 동작의 빈 그릇(노이즈 액션)"은 실행하는 뇌로 갑니다.
System 2 — Vision-Language 이해 (Eagle-2 VLM)
블록도 상 위치: 전체 파이프라인 입력 직후, 좌측 System 2 박스 전체(이미지+언어 지시를 받아 VL 토큰을 만들어 System 1으로 넘기는 부분). 그 내부에 SigLIP-2(이미지 인코더)와 SmolLM2(언어 모델)가 하위 블록으로 들어있습니다.
전문적으로: 백본은 Eagle-2 VLM으로, SigLIP-2(이미지 인코더)와 SmolLM2(언어 모델)를 NVIDIA가 자체 데이터 전략으로 파인튜닝한 것입니다. 공개된 SmolVLM2를 그대로 쓴 것이 아니라, 범용 프론티어급 VLM을 목표로 더 크고 무겁게 재학습한 별도 모델입니다. 처리 과정은 다음과 같습니다. 이미지는 224×224로 맞춰진 뒤 SigLIP-2를 거치고, pixel shuffle로 압축되어 프레임당 64개의 토큰이 됩니다. 이 이미지 토큰과 텍스트 토큰을 하나의 시퀀스로 concatenation하여 SmolLM2에 함께 입력하고, self-attention을 거치며 둘이 융합됩니다. 출력으로는 최종 레이어가 아니라 12번째 레이어의 중간 hidden state를 사용하는데, 이것이 추론 속도와 다운스트림 policy 성공률 모두에서 더 나았다고 논문이 실험적으로 밝힙니다(이론적 근거는 제시되지 않음). 출력 형태는 (batch × sequence length × hidden dim)으로, 하나의 벡터가 아니라 여러 토큰이 쌓인 행렬입니다. sequence length는 이미지 64토큰(고정) + 언어 N토큰(가변)입니다.
직관적으로: 이미지를 잘게 쪼개 64개의 "시각 조각"으로 만들고, 언어 토큰과 한 줄로 나란히 얹어서 언어 모델에 통째로 넣습니다. 그러면 "컵을 집어"라는 말과 "화면 속 컵"이 서로 참고하며 섞여, "지금 상황과 목표"에 대한 이해가 만들어집니다. 그리고 이 이해는 끝까지 안 가고 중간(12번째 층)에서 뽑아 쓰는데, 지나치게 추상화된 최종 출력보다 시각·공간 디테일이 살아있는 중간 표현이 로봇 제어엔 더 유리했기 때문으로 보입니다.
🖼️ [그림: SigLIP-2 pixel shuffle 압축 과정] — 좌측에 224×224 이미지, 화살표로 "SigLIP-2" 박스를 거쳐 작은 패치 조각들(예: 256개 격자)이 나열된 그림. 그다음 화살표로 "pixel shuffle" 박스를 거치면서 여러 개의 작은 조각이 4개씩 묶여 1개의 더 큰(정보량 많은) 조각으로 합쳐지는 모습(예: 256개 → 64개로 개수는 줄고 각 조각의 두께/크기는 두꺼워지는 시각적 표현). 최종적으로 "64개 이미지 토큰" 박스로 도착.
pixel shuffle이란: 블록도 상 위치는 SigLIP-2 바로 뒤, 이미지 인코딩 파이프라인의 압축 단계입니다. 이미지를 잘게 나눈 여러 조각 벡터를 몇 개씩 묶어서, 개수는 줄이되 각 벡터의 정보량은 늘리는 압축 방식입니다. 토큰 개수가 많을수록 트랜스포머 연산량이 제곱으로 커지므로, 로봇처럼 빠르게 반복 계산해야 하는 상황에서 속도를 확보하기 위해 이미지를 64토큰으로 압축하는 것입니다.
참고 (SmolVLA · π0와의 계보): GR00T의 이미지 처리(SigLIP + pixel shuffle + 정확히 64토큰, 그리고 중간층 사용)는 SmolVLA와 같은 계보입니다. SmolVLA도 같은 방식으로 64토큰을 만들고, "layer skipping"으로 중간층을 쓴다는 점까지 같은 발상입니다. 반면 π0는 PaliGemma 기반으로 pixel shuffle 없이 224 해상도에서 256토큰을 그대로 쓰는 다른 계보입니다. 즉 GR00T의 비전 처리는 π0보다 SmolVLA에 훨씬 가깝습니다.
System 1 — 실행 (Diffusion Transformer)
블록도 상 위치: 전체 파이프라인의 우측 하단, State/Action Encoder의 출력과 System 2가 만든 VL 토큰을 함께 받아 최종 동작을 만들어내는 부분 전체입니다.
이름에 대한 주의: DiT인데 diffusion이 아니다
전문적으로: System 1은 "Diffusion Transformer(DiT)"라는 아키텍처를 사용하지만, 학습 방법론은 diffusion이 아니라 flow matching입니다. DiT는 Peebles & Xie(2023)가 제안한 트랜스포머 구조의 고유명사이며, 원래는 diffusion을 위해 만들어졌지만, 이후 커뮤니티에서 이 구조에 flow matching이라는 다른 학습 목적함수를 얹는 것이 흔한 패턴이 되었습니다. GR00T는 이 DiT 구조(self-attention, cross-attention, FFN, adaptive layer norm 기반 timestep 조건화)만 차용하고 학습 목적함수는 flow matching으로 대체했습니다.
직관적으로: "DiT"는 학습 방식이 아니라 구조(뼈대)의 이름입니다. 이름에 diffusion이 들어 있다고 diffusion으로 학습하는 게 아닙니다. 원조 브랜드 이름이 범용 명칭처럼 굳어진 경우라고 보면 됩니다. GR00T는 "DiT라는 뼈대에 flow matching이라는 학습법을 얹은 것"입니다.
System 1의 입력과 토큰 구조
🖼️ [그림: 토큰 shape 진행도] — 좌측에 "로봇 상태(1토큰)"와 "노이즈 액션(16토큰)" 박스가 나란히 있다가 화살표로 합쳐져 "17토큰 시퀀스" 박스가 됨. 그다음 화살표로 "DiT 블록들 통과 (shape 유지, 17토큰)" 박스. 그다음 화살표로 "액션 16토큰만 추출 (상태 1토큰 버림)" 박스, 버려지는 상태 토큰은 점선/회색으로 표시. 각 박스 아래에 shape 표기: (batch, 17, hidden) → (batch, 17, hidden) → (batch, 16, hidden).
🖼️ [그림: DiT 블록 내부 self/cross-attention 흐름] — self-attention(로봇 상태 + 노이즈 액션끼리) → cross-attention(VL 토큰을 K,V로 참조) 순서로 번갈아 반복되는 구조. VL 토큰은 옆에서 "참고자료"로 대기하며 항상 K,V로만 쓰이고 Q가 되지 않음을 화살표로 표시.
전문적으로: System 1 관점의 입력은 세 가지입니다. VL 토큰(System 2 출력), 로봇 상태, 노이즈 액션입니다. 이때 로봇 상태는 1개 토큰(state embedding $q_t$)으로, 노이즈 액션은 H=16개 토큰($A_t^\tau = [a_t, ..., a_{t+15}]$)으로 인코딩되어, 둘이 이어붙어 17토큰 시퀀스가 됩니다. self-attention과 cross-attention은 모두 이 17토큰 위에서 작동합니다. 마지막 DiT 블록 이후에는 액션에 해당하는 16토큰만 추출하여 디코더로 넘기며, 상태 토큰 1개는 이 시점에서 버려집니다(그 정보는 이미 attention을 거치며 액션 토큰에 흡수된 상태입니다). 중요한 점은 이 16개 액션 토큰이 순차적으로 하나씩이 아니라 한 번의 forward pass에서 병렬로 동시에 처리된다는 것입니다. 이것이 "액션 청킹(action chunking)"의 핵심으로, 미래 16타임스텝을 한꺼번에 예측하기에 빠르고, 스텝 간 self-attention으로 서로를 참고하여 부드럽게 이어지는 동작을 만듭니다.
직관적으로: 이해 담당이 넘긴 "상황 요약(VL 토큰)"과 "내 몸 상태", "채울 동작 그릇"이 System 1으로 들어옵니다. 동작 그릇은 미래 16스텝치가 한 줄로 나란히 준비되어 있고, 이 16개가 동시에 처리됩니다. 한 스텝씩 순서대로 만드는 게 아니라 16개를 통째로 한 번에 만들기 때문에 빠르고, 서로 참고하며 만들어지니 급격히 튀지 않고 자연스럽게 이어집니다.
DiT 블록 — self-attention, cross-attention, FFN
블록도 상 위치: System 1 내부, State/Action Encoder 출력을 받아 반복적으로 정제하는 핵심 연산 블록입니다.
전문적으로: DiT 블록은 self-attention과 cross-attention이 번갈아 나오는 구조(Flamingo/VIMA 계열)이며, 각 어텐션 뒤에 표준적으로 FFN(feed-forward network)이 붙습니다. self-attention 단계에서는 로봇 상태와 노이즈 액션이 서로 Q, K, V를 모두 담당하며, cross-attention 단계에서는 로봇 상태+액션이 Q를, VL 토큰이 K, V를 담당합니다. VL 토큰은 절대 Q가 되지 않는데, 이것이 System 2가 System 1을 참조하지 못하는 단방향성의 구조적 구현입니다(π0가 하나의 시퀀스에서 attention masking으로 미래를 차단한 것과 같은 효과를, GR00T는 아예 모듈을 분리하고 cross-attention 방향을 고정하여 달성합니다). 각 블록의 attention과 FFN에는 diffusion timestep을 조건화하는 adaptive layer norm이 적용됩니다. FFN은 N1.5에서 새로 생긴 것이 아니라 원조 DiT부터 있던 표준 구성요소입니다(정확한 차원 수치는 N1 논문에 명시되지 않음).
직관적으로: 두 단계가 서로 다른 역할을 합니다. self-attention은 "이 동작이 지금 내 몸 상태에서 물리적으로 가능한가"를 다듬는 단계입니다(예: 이미 최대로 뻗은 팔에게 "더 뻗어라"는 모순을 걸러냄). cross-attention은 "그 동작이 지금 해야 할 일과 보이는 상황에 맞는가"를 다듬는 단계입니다. 이 둘을 번갈아 여러 번 반복하며 "몸에 맞게 → 목표에 맞게 → 다시 몸에 맞게"를 오가며 동작을 정교하게 수렴시킵니다. 이때 VL 토큰(이해)은 "가만히 놓인 참고서"이고, 로봇 상태+액션이 그 참고서를 계속 들춰보며 답을 다듬습니다. 참고서 자체는 바뀌지 않고, 답안지(액션)만 계속 고쳐집니다. FFN은 일반 트랜스포머와 마찬가지로 각 어텐션 뒤에 붙어 표현을 한 번 더 가공하는 표준 부품입니다.
Flow matching과 4번 반복 (되먹임)
블록도 상 위치: 별도의 박스가 아니라, System 1(DiT 블록 + Action Decoder)을 통째로 4번 반복시키는 제어 흐름 자체입니다.
🖼️ [그림: 되먹임 루프] — 노이즈 액션 → Action Encoder → DiT 블록 → Action Decoder로 이어지고, Action Decoder의 출력이 다시 노이즈 액션 자리로 되돌아가는 순환 화살표. 옆에 "System 1 전체를 4번 반복", 최종 출력 옆에 "4번째 반복 후에만 최종 동작 명령으로".
전문적으로: 액션 청크는 매 추론 시점 순수 가우시안 노이즈 $A_t^0 \sim \mathcal{N}(0,I)$에서 새로 시작합니다(이전 시점의 청크를 재사용하는 피드백이 아닙니다). DiT는 velocity field $V_\theta(\phi_t, A_t^\tau, q_t) \approx \epsilon - A_t$를 예측하고, K=4 스텝 forward Euler integration으로 점진적으로 정제합니다($A_t^{\tau+1/K} = A_t^\tau + \frac{1}{K}V_\theta$). 각 스텝에서 갱신된 액션이 다음 스텝의 입력으로 되먹임되며, 이때 DiT의 가중치는 변하지 않고 동일한 네트워크를 4번 통과합니다. 여기서 예측하는 velocity는 물리적 힘이 아니라 "노이즈 공간에서 실제 액션 공간으로 가는 방향"을 나타내는 수학적 변위 벡터입니다.
직관적으로: 백지(랜덤 노이즈)에서 시작해 같은 화가(DiT)가 4번 덧칠하는 것과 같습니다. 매 붓질마다 결과물을 다시 보고 더 다듬어, 4번째에 노이즈가 다 걷힌 최종 동작이 나옵니다. DiT 자체(가중치)는 안 변하고, 캔버스에 그려진 동작 값만 매번 갱신되어 다음 붓질의 재료가 됩니다. velocity는 실제 힘이 아니라 "목적지 방향을 가리키는 나침반 바늘" 같은 것으로, "지금 이 노이즈에서 진짜 액션 쪽으로 얼마나, 어느 방향으로 이동해야 하는지"를 알려주는 값입니다.
flow matching이 diffusion과 다른 점: diffusion은 노이즈 자체를 예측하며 구불구불한 확률적 경로를 따라 수십~수백 스텝을 거치지만, flow matching은 velocity(방향)를 예측하며 노이즈에서 데이터로 가는 거의 직선에 가까운 경로를 따라가서 K=4처럼 적은 스텝으로도 충분합니다.
Action Decoder
블록도 상 위치: System 1의 맨 끝, DiT 블록이 내놓은 16개 액션 토큰을 받아 실제 관절값으로 바꾸는 출구입니다.
전문적으로: 마지막 DiT 블록 이후, 액션 위치의 16토큰에 embodiment-specific Action Decoder(MLP)를 적용하여 velocity를 해당 로봇의 실제 액션 차원으로 변환합니다. 이 디코더는 K=4의 각 denoising 스텝마다 호출됩니다. 변환은 하드코딩된 규칙이 아니라 순수하게 학습된 가중치 행렬로 이루어지며, "어떤 임베딩 차원이 어떤 관절에 대응하는지"는 실제 로봇 궤적을 정답으로 한 역전파를 통해 가중치 안에 암묵적으로 인코딩됩니다.
직관적으로: DiT가 뱉은 "추상적 방향 벡터"를 "이 로봇의 실제 관절값"으로 번역하는 출구입니다. 사람이 "이 숫자는 팔꿈치다"라고 규칙을 짜준 게 아니라, 학습을 통해 저절로 그렇게 정렬되도록 최적화된 번역기입니다.
Embodiment별 처리 — 왜 입구와 출구를 로봇마다 나눴는가
블록도 상 위치: 입력(로봇 상태·노이즈 액션)과 System 1 사이의 State/Action Encoder, 그리고 System 1 출력 뒤의 Action Decoder — 이 둘이 로봇별로 나뉘는 지점입니다.
🖼️ [그림: Embodiment별 MLP 차원 매핑] — 왼쪽에 서로 다른 크기의 입력 박스 2개("SO-101, 7차원", "휴머노이드, 25차원"), 각각 다른 화살표로 서로 다른 색의 "State Encoder(SO-101 전용)"와 "State Encoder(휴머노이드 전용)" 박스를 거쳐, 두 화살표가 오른쪽의 동일한 크기 박스 "공통 임베딩(1536차원)"으로 합류. 두 Encoder 박스는 서로 다른 가중치임을 나타내기 위해 다른 색/패턴으로 구분.
전문적으로: 로봇마다 상태/액션 차원이 다릅니다(SO-101은 약 6-7차원, 양팔 휴머노이드는 약 20-30차원). 트랜스포머(DiT)는 고정 차원 입력을 요구하므로, State Encoder, Action Encoder, Action Decoder를 embodiment별 전용 MLP로 두어 "각 로봇 고유 차원 ↔ 공통 임베딩 차원"을 변환합니다. 예를 들어 SO-101용 인코더는 7차원을 공통 차원으로, 휴머노이드용 인코더는 25차원을 같은 공통 차원으로 투영합니다. 두 인코더는 입력 차원이 다르니 가중치 행렬 자체의 모양도 다르지만, 출력은 같은 크기로 통일됩니다. DiT 본체는 모든 로봇이 완전히 공유하며, 여기서 cross-embodiment transfer가 일어납니다. 입구(고유→공통)와 출구(공통→고유)는 방향만 반대인 같은 성격의 작업이라 둘 다 대칭적으로 로봇별로 둡니다.
직관적으로: 로봇마다 관절 개수가 다른데, 이걸 하나의 DiT에 넣으려면 크기를 맞춰야 합니다. 입구와 출구에 로봇별 통역기(MLP)를 두어 "무슨 로봇이든 같은 크기의 벡터로" 바꿔줍니다. 여러 나라 사람이 각자 자기 언어로 말해도(로봇별 통역기), 회의실 안 토론은 하나의 공용어로 진행되는(공유 DiT) 것과 같습니다. 통역기만 로봇별로 두고, 실제 지능(DiT)은 다 같이 공유하니, SO-101에서 배운 "물건 잡는 일반적 패턴"이 휴머노이드 학습에도 영향을 줍니다.
Embodiment Tag — DiT는 로봇을 전혀 모른다
블록도 상 위치: 입력 데이터와 각 Encoder/Decoder를 잇는 라우팅 지점입니다. DiT 블록 내부에는 존재하지 않습니다.
🖼️ [그림: Embodiment Tag 라우팅] — 입력 데이터(로봇 상태·노이즈 액션)에 🏷 태그 표시, State/Action Encoder와 Action Decoder에는 "🏷 태그로 MLP 선택", DiT 블록에는 "태그 모름 — 모든 로봇 동일 연산"을 대비되게 표기.
전문적으로: 각 데이터에는 EmbodimentTag(예: GR1, UNITREE_G1)가 메타데이터로 부착되며, 이 태그에 따라 어떤 State/Action Encoder와 Decoder를 쓸지 라우팅됩니다. DiT 본체는 이 태그를 보지 않으며, 로봇 정체성 정보는 hidden 벡터가 아니라 시스템 레벨의 태그 라우팅으로 처리됩니다. 즉 인코더가 이미 로봇 간 차이를 "지워서" 같은 크기의 벡터로 만들어 넘기므로, DiT는 그 벡터가 어떤 로봇에서 왔는지 구별할 방법도 필요도 없습니다.
직관적으로: "지금 이 데이터는 SO-101 것"이라는 이름표(태그)가 붙어 있어서, 그 이름표를 보고 어떤 통역기를 쓸지 고릅니다. DiT는 이름표를 보지 않고, 그냥 들어온 벡터를 항상 똑같이 계산할 뿐입니다. DiT는 자기가 지금 어떤 로봇을 다루는지 아예 모릅니다. 이것이 "DiT 본체를 모든 로봇이 공유한다"는 말의 진짜 의미로, 단순히 같은 가중치를 쓴다는 수준을 넘어 "로봇이 다르다는 사실 자체를 인지할 수 없는 구조"라는 뜻입니다.
파이프라인 전체를 관통하는 원리: 실제 값의 의미는 끊기지 않는다
전문적으로: 학습 데이터의 ground-truth 자체가 실제 로봇 관절 기록이므로, State/Action Encoder는 "실제 단위 → 추상 임베딩"의 입구 번역기, Action Decoder는 "추상 임베딩 → 실제 단위"의 출구 번역기 역할을 합니다. DiT 내부는 추상 임베딩 공간에서 작동하지만, 그 공간 자체가 실제 물리량을 왕복 가능하도록 학습된 표현입니다. 따라서 형태(추상 벡터 ↔ 실제 값)는 바뀌어도, 그것이 담은 의미(그 로봇의 실제 물리적 상태·동작)는 파이프라인 전체에 걸쳐 끊기지 않습니다.
직관적으로: 한국어 → 영어 → 한국어 번역과 같습니다. 중간에 영어(추상 벡터)를 거치지만, 그 영어가 애초에 원래 뜻(실제 로봇 동작)을 보존하도록 학습되었기에 처음 의미가 끝까지 이어집니다. 중간에 의미가 진공 상태로 끊기는 지점은 없습니다.
학습 효율과 그 해석
전문적으로: GR00T N1은 data-efficient post-training을 목표로 설계되어, 적은 데이터로도 새 과업에 빠르게 적응합니다. 예를 들어 Fourier GR-1 pick-and-place에서 전체 데이터로는 82% 성공률이지만 데이터의 10%만으로도 42.6%를 기록합니다(성능은 데이터가 줄면 떨어지되 급락하지 않고 완만하게 저하됩니다). 다만 이 데이터 효율이 어느 설계 요소(대규모 사전학습, Eagle-2 VLM, embodiment별 MLP, flow matching의 샘플 효율성) 덕분인지는 논문이 분리 검증(ablation)하지 않았습니다. embodiment별 MLP 구조가 cross-embodiment 학습을 가능케 하는 구조적 전제조건이라는 점에서 "영향을 준다"는 것은 확실하지만, 그 정량적 기여도는 알 수 없습니다.
직관적으로: 새 로봇을 추가할 때 전체 2.2B를 다시 학습하는 게 아니라 작은 통역기(MLP)만 새로 학습하면 되므로, 적은 데이터로도 꽤 잘 작동합니다. 다만 "이 좋은 효율이 정확히 어떤 설계 하나 덕분인가"는 여러 요소가 뒤섞인 결과라 딱 잘라 말할 수 없습니다.
부록 — 배경 (왜 이렇게 만들었는가)
🖼️ [그림: π0 vs GR00T 연결 구조 비교도] — 좌우 2단 비교. 왼쪽(π0): 하나의 큰 트랜스포머 박스 안에 이미지·언어·상태·액션 토큰이 한 줄로 나란히 들어있고, 액션 쪽에서 이미지·언어 쪽으로 향하는 화살표에 X 표시(마스킹으로 차단). 오른쪽(GR00T): System2 박스와 System1 박스가 완전히 분리되어 있고, 그 사이를 단방향 화살표 하나(System1→System2, cross-attention)만 연결. 하단에 각각 "같은 공간 + 마스킹 규칙" / "다른 공간 + 한쪽 문(cross-attention)"이라고 표기.
전문적으로: GR00T N1 이전에는 두 가지 접근과 그 한계가 있었습니다. 첫째, cross-embodiment pooling(예: Open X-Embodiment)은 여러 로봇 데이터를 그냥 모으는 방식인데, 로봇 간 이질성 때문에 하나의 일관된 데이터셋이 아니라 서로 단절된 "data island(데이터 섬)"들의 집합이 되어버렸습니다. GR00T는 이를 데이터 피라미드로 대응합니다. 둘째, mixture-of-experts 기반 VLA(예: π0)는 하나의 트랜스포머에 모든 토큰을 넣고 마스킹으로 통제하는 방식인데, GR00T는 System 1과 System 2를 아예 분리하고 단순한 cross-attention으로만 연결하여, 더 단순할 뿐 아니라 VLM과 액션 모델을 독립적으로 교체·업그레이드할 수 있게 했습니다.
직관적으로: 예전엔 여러 로봇 데이터를 그냥 한데 모으려다 서로 안 맞아 실패했고(첫째), 한 모델 안에 다 욱여넣고 복잡한 방식으로 연결했습니다(둘째). GR00T는 첫째 문제를 "데이터를 계층으로 정리(피라미드)"해서, 둘째 문제를 "두 뇌를 분리하고 한쪽만 참조(cross-attention)"해서 더 단순하게 풀었습니다. 앞서 본 데이터 피라미드와 cross-attention 구조가 바로 이 두 문제에 대한 답이었던 셈입니다.
이 글은 GR00T N1(arXiv 2503.14734)을 기준으로 하며, N1.5 이후 버전(DreamGen 등)의 수치는 포함하지 않았습니다. 일부 세부 구현(정확한 hidden dimension 등)은 원 논문에 명시되지 않아 생략했습니다.
|
|

첫댓글 정리를 너무 잘했어요
ACT와 VLA모델에서 action decoder로 각각 사용되고 있는 VAE(variational autoencoder,변분오토인코더)와 Diffusion model(확산모델)도 공부해보세요 2개 모두 생성형 모델입니다.