Modern Robotics и Physical AIУрок 1.6 · Трансформер
1.6 Часть 1 · Ядро · основы

Трансформер

Политике нужно одновременно читать несколько камер, команду и состояние суставов, а на выходе выдавать последовательность действий. RT-1, ACT, Octo, π0 и GR00T делают это трансформером. В уроке мы разберём внимание на шести токенах, которые можно двигать руками, а потом посчитаем, во что обходятся токены у настоящих политик и почему частота управления не равна частоте вывода. Если трансформер знаком, урок можно пропустить.

≈ 45 минут1 лаборатория и 5 интерактивов10 задач с целью
ТОКЕНЫНарежь кадр кухни на патчи и посчитай, во сколько раз дорожает внимание
ВНИМАНИЕНаведи запрос на чашку, найди ответ между предметами и не дай softmax схлопнуться
МАСКА И ГОЛОВЫСобери маску π0 по клеткам и настрой две головы на одной сцене
ПОРЯДОКНайди команды, которые без позиционных кодировок неразличимы
СТОИМОСТЬДобавь π0 четвёртую камеру и уложись в прежний бюджет внимания
ВЫВОД π0Найди, куда уходят 73 мс и как они дают управление на 50 Гц

Начать урок ↓

1 Входы политики

Сколько входов у политики

Возьмём π0. На каждом шаге модель получает кадры трёх камер, текстовую команду вроде «убери чашку в раковину» и состояние робота, а выдаёт пачку из 50 действий. Кадр — это тысячи пикселей, команда — несколько слов, состояние — короткий вектор чисел. Входы разной природы и разного размера, и прочитать их должна одна сеть.

Трансформер решает это одним приёмом: всё превращается в токены, векторы одинаковой длины. Кадр режут на квадратные патчи, команду — на слова и их части, состояние проходит через линейный слой и становится одним токеном. Дальше сеть работает с цепочкой токенов. Связи между ними устанавливает внимание: каждый токен решает, на какие другие ему смотреть и что у них взять.

Вход π0 в токенахоколо 870 токенов на шаг (расчёт по коду openpi)
  • 768 кадры трёх камер, по 256 токенов на картинку 224 px
  • до 48 команда
  • 1 состояние робота
  • 50 действий пачки
2 Токены

Как картинка становится токенами

Vision Transformer (ViT, 2021) режет картинку на квадратные патчи, вытягивает каждый в вектор и проецирует линейным слоем. Патч становится токеном, как слово в предложении. Чем мельче патч, тем больше токенов и тем лучше сеть видит детали. Но внимание сравнивает каждый токен с каждым, поэтому число пар растёт как квадрат числа токенов.

Перед тобой кадр со стола Ады, 224 × 224 пикселя. Сделай ставку, потом переключай размер патча и наводи курсор на кадр.

Ада — домашний гуманоидный робот, на котором построены лабораторные работы курса. Подробнее о ней — в уроке 0.1.

49токенов на картинку
2 401пар для внимания, n2n^2
Под капотом: ViT и откуда 196 токенов
N=HWP2,z0=[xclass; x1E; x2E; …; xNE]+Epos,E∈R(P2C)×D.\begin{gathered} N = \frac{H W}{P^2},\\ z_0 = \bigl[x_{\text{class}};\ x^1 E;\ x^2 E;\ \ldots;\ x^N E\bigr] + E_{\text{pos}},\\ E \in \mathbb{R}^{(P^2 C) \times D}. \end{gathered}

Картинка H×WH \times W с CC каналами режется на NN патчей P×PP \times P. Каждый патч вытягивается в вектор из P2CP^2 C чисел и умножается на матрицу EE, спереди добавляется токен [class], к каждому токену — обучаемая позиция. Для 224 × 224 и P=16P = 16 выходит 14 × 14 = 196 патчей и ещё [class] (расчёт). ViT-B — 12 слоёв, D=768D = 768, 12 голов, 86M параметров.

Трансформер не всегда лучше свёрточной сети. На ImageNet без сильной регуляризации ViT на несколько пунктов хуже ResNet и догоняет лучшие модели только при 14–300 млн картинок для обучения. Поэтому в RT-1 и ACT картинки кодирует свёрточная сеть: RT-1 получает из кадра 300 × 300 81 токен, а TokenLearner сжимает её до 8 токенов на кадр. Вывод от этого ускоряется в 2,4 раза.

🔬 Лаборатория

Найди чашку: внимание по шагам

Ада ищет на столе чашку. Каждый из шести предметов — токен. У токена есть ключ: вектор, по которому его находят. И есть значение: то, что токен отдаёт, если его выбрали. У нас значение предмета — его место на столе. Запрос «где чашка» сравнивается с каждым ключом скалярным произведением, softmax превращает оценки в веса, а ответ внимания — сумма значений с этими весами. Всё считается вручную на двумерных векторах, которые ты двигаешь сам. Ручки появляются от миссии к миссии.

Стол Адывид сверху; кольцо — вес предмета
Ключи и запросперетаскивай конец толстой стрелки
Веса softmax
Под капотом: формулы внимания, головы и маски
Attention⁡(Q,K,V)=softmax⁡(QKTdk+M)V,Q∈Rn×dk,K∈Rm×dk,V∈Rm×dv.\begin{gathered} \operatorname{Attention}(Q, K, V) = \operatorname{softmax}\Bigl(\frac{Q K^{\mathsf T}}{\sqrt{d_k}} + M\Bigr) V,\\ Q \in \mathbb{R}^{n \times d_k}, \quad K \in \mathbb{R}^{m \times d_k}, \quad V \in \mathbb{R}^{m \times d_v}. \end{gathered}

Softmax берётся по строкам: у каждого запроса веса в сумме дают 1. Зачем делить на dk\sqrt{d_k}: если компоненты qq и kk независимы, со средним 0 и дисперсией 1, то дисперсия q⋅kq \cdot k равна dkd_k. При больших dkd_k оценки разбегаются, softmax уходит в область, где почти весь вес у одного токена, а градиенты крошечные.

MultiHead⁡(Q,K,V)=Concat⁡(head1,…,headh) WO,headi=Attention⁡(QWiQ, KWiK, VWiV),WiQ,WiK∈Rdmodel×dk,WiV∈Rdmodel×dv,WO∈Rhdv×dmodel,dk=dv=dmodel/h.\begin{gathered} \operatorname{MultiHead}(Q, K, V) =\\ \operatorname{Concat}(\text{head}_1, \ldots, \text{head}_h)\, W^O,\\ \text{head}_i = \operatorname{Attention}(Q W_i^Q,\ K W_i^K,\ V W_i^V),\\ W_i^Q, W_i^K \in \mathbb{R}^{d_{\text{model}} \times d_k}, \quad W_i^V \in \mathbb{R}^{d_{\text{model}} \times d_v},\\ W^O \in \mathbb{R}^{h d_v \times d_{\text{model}}}, \quad d_k = d_v = d_{\text{model}} / h. \end{gathered}

У каждой головы свои матрицы, поэтому головы смотрят на разные признаки. Ширина головы — dmodel/hd_{\text{model}}/h, так что все головы вместе стоят почти как одна голова полной размерности. Self-attention: QQ, KK и VV берутся из одной последовательности. Cross-attention: QQ из одной, KK и VV из другой. Так запросы действий в ACT читают признаки картинок, а DiT в GR00T N1 — признаки VLM.

Маска MM: 0 там, где токену ii можно смотреть на токен jj, и −∞-\infty там, где нельзя. Каузальная маска закрывает всё правее диагонали: Mij=−∞M_{ij} = -\infty при j>ij > i. Блочная маска π0 и prefix-LM в PaliGemma открывает клетку, если номер блока у jj не больше, чем у ii: внутри блока внимание идёт в обе стороны, между блоками — только назад. Маска паддинга закрывает столбцы пустых токенов.

Блок 2017 года и его полносвязный подслой:

x←LayerNorm⁡(x+Sublayer⁡(x)),FFN⁡(x)=max⁡(0, xW1+b1) W2+b2.\begin{gathered} x \leftarrow \operatorname{LayerNorm}\bigl(x + \operatorname{Sublayer}(x)\bigr),\\ \operatorname{FFN}(x) = \max(0,\ x W_1 + b_1)\, W_2 + b_2. \end{gathered}

В ViT и Gemma норма стоит до подслоя:

x←x+Sublayer⁡(Norm⁡(x)).x \leftarrow x + \operatorname{Sublayer}\bigl(\operatorname{Norm}(x)\bigr).

Как устроена лаборатория. У предмета два признака: цвет (красный, синий, белый) и место (у переднего края, в середине, в глубине стола). Ключ общей головы — вектор цвета плюс 0,7 вектора места, поэтому все шесть ключей разные. Голова «цвет» видит только цвет, голова «место» — только место, у них ключи длиной 1,4. Значение предмета — его координаты на столе 1 × 1 м. Длина запроса — до 3. При dk>2d_k > 2 к двум видимым компонентам добавляются dk−2d_k - 2 скрытых: случайные числа с дисперсией 1, одни и те же при каждом запуске (зерно 169). Пороги миссий: вес чашки больше 0,5; ответ дальше 15 см от центров предметов при весах не больше 0,6; наибольший вес меньше 0,9; у пар больше 0,8 и у чашки больше 0,3 в обеих головах.

3 Позиции

Внимание не знает порядка

Сумма с весами не зависит от того, в каком порядке стоят слагаемые. Если переставить токены, каждый унесёт свой вес с собой, и ответ не изменится. Для робота это проблема: «возьми чашку, потом миску» и «возьми миску, потом чашку» — разные команды. Поэтому к токенам добавляют позиционные кодировки: векторы, которые зависят только от номера позиции. В статье 2017 года это синусоиды разных частот.

Ниже — команда из четырёх токенов-слов. Токен действия спрашивает у них: какой предмет взять первым? Переставляй слова и ищи команды, на которых Ада ошибётся.

Команда — перетащи слово или нажми два слова, чтобы поменять их местами
Выход внимания: 4 числа содержания и 16 чисел позиции
0найдено отказов: команд, где Ада берёт первым не тот предмет
Сходство позиционных кодировок

Каждая клетка — косинусное сходство кодировок двух позиций, 16 чисел на позицию. Наведи курсор на клетку. Рамкой отмечены позиции 0–3, на которых стоит команда.

Под капотом: синусоиды, RoPE и наша игрушечная команда
PE(pos,2i)=sin⁡(pos/100002i/dmodel),PE(pos,2i+1)=cos⁡(pos/100002i/dmodel).\begin{aligned} \mathrm{PE}(\mathit{pos}, 2i) &= \sin\bigl(\mathit{pos} / 10000^{2i/d_{\text{model}}}\bigr),\\ \mathrm{PE}(\mathit{pos}, 2i + 1) &= \cos\bigl(\mathit{pos} / 10000^{2i/d_{\text{model}}}\bigr). \end{aligned}

Каждая пара чисел — синусоида своей частоты: от одного оборота за 6,3 позиции до очень медленных. Соседние позиции получают похожие векторы, далёкие — менее похожие. Синусоиды в статье 2017 года выбрали в расчёте на последовательности длиннее, чем при обучении. Обученные позиционные эмбеддинги дали почти тот же результат. В ACT позиции картинок — двумерные синусоиды, в Decision Transformer — эмбеддинг шага по времени, в Gemma — RoPE: он поворачивает векторы запроса и ключа на угол, который зависит от позиции.

Наша команда. Токен слова — 4 числа содержания (по одному на слово) и 16 чисел позиции; без позиций они нулевые. Запрос токена действия любит предметы, чашку чуть больше миски: так вышло при «обучении». Ещё он любит начало команды: его позиционная часть совпадает с кодировкой позиции 0. Ответ — предмет с большим весом. Без позиций чашка выигрывает всегда, и Ада ошибается во всех 12 командах из 24, где миска идёт раньше чашки. С позициями ранний предмет получает больший вес, и ошибок нет ни в одной из 24 перестановок.

4 Стоимость

Сколько стоят токены

Внимание сравнивает каждый токен с каждым: удвой число токенов — пар станет вчетверо больше. Но квадратично дорожает только этот член. Проекции Q, K, V и полносвязный блок обрабатывают токены по одному, их стоимость растёт линейно. У π0 около 870 токенов при ширине модели 2048, и большую часть вычислений слоя пока забирают именно они. Камеры и разрешение — это бюджет: каждая новая камера добавляет сотни токенов.

Калькулятор считает длину последовательности, грубую стоимость прохода и размер KV-кэша. Пресеты задают входы настоящих политик. Ширину и глубину модели выбираешь сам, поэтому все пресеты сравниваются на модели одного размера, по умолчанию как у π0.

Пресет:
Вход
Нарезка
Выход
Модель
867токенов в последовательности

Под капотом: что считает калькулятор
  • внимание: 4n2dL4 n^2 d L FLOPs — произведение QKTQ K^{\mathsf T} и смесь значений VV;
  • проекции и FFN: 24nd2L24 n d^2 L FLOPs — матрицы QQ, KK, VV, OO и FFN шириной 4d4d;
  • KV-кэш: 2LHkvdheadT2 L H_{kv} d_{\text{head}} T чисел, по 2 байта в bf16.

Это грубая оценка для обычного блока трансформера: умножение и сложение считаем за две операции, FFN шириной 4dmodel4 d_{\text{model}}, нормы и softmax не считаем. В настоящих моделях FFN бывает шире, тогда доля внимания ещё меньше. Vaswani и соавторы сравнивали так же: слой self-attention стоит O(n2d)O(n^2 d), рекуррентный — O(nd2)O(n d^2), и внимание дешевле, пока n<dn < d. У π0 n≈870n \approx 870 при dmodel=2048d_{\text{model}} = 2048 (расчёт).

FlashAttention квадратичность не убирает: FLOPs остаются O(n2d)O(n^2 d), зато дополнительная память — O(n)O(n), а ускорение получается за счёт меньшего числа обращений к памяти GPU. KV-кэш считаем для префикса — токенов наблюдения. У Gemma 2B в π0 18 слоёв, одна KV-голова и dhead=256d_{\text{head}} = 256: около 18 КБ на токен в bf16, а префикс из 816 токенов — около 15 МБ (расчёт). Калькулятор держит одну KV-голову с dhead=256d_{\text{head}} = 256 для любой ширины модели. Памяти кэш у π0 берёт мало, дорого время: энкодеры и проход по наблюдению занимают 46 мс из 73.

5 KV-кэш и пачки

Почему 73 мс дают 50 Гц

Когда модель строит выход за несколько шагов, ключи и значения уже обработанных токенов не меняются. Их считают один раз и сохраняют. Это KV-кэш. В π0 так кэшируют наблюдение — картинки и команду: блочная маска из лаборатории гарантирует, что оно не зависит от действий. Пачку действий модель уточняет за 10 шагов flow matching (урок 1.8), и каждый шаг читает готовые K и V вместо того, чтобы снова прогонять 816 токенов наблюдения.

Вторая идея — пачки. π0 выдаёт сразу 50 действий, а модель перезапускают раз в 0,5 с. Робот получает новое действие каждые 20 мс, хотя модель вызывают дважды в секунду. Ниже — вывод π0 на RTX 4090 с тремя камерами. Нажимай на блоки и на ленту тиков.

Вывод: 73 мс
Лента управлениякаждая клетка — тик 20 мс; нажми на тик
Под капотом: цифры вывода и как устроены другие системы

π0 — 3,3B параметров: Gemma 2B с энкодером картинок SigLIP и action expert на 300M. Вывод на RTX 4090 с тремя камерами: энкодеры картинок 14 мс, проход по наблюдению 32 мс, 10 шагов flow matching 27 мс, всего 73 мс. Если модель работает не на компьютере робота, добавляется сеть: 86 мс. Время «без кэша» — наша оценка по той же схеме: 14 + 10 × (32 + 2,7) ≈ 361 мс. KV-кэш работает только на выводе: при обучении и в первом проходе считать всё равно нужно.

В работе о real-time chunking (Black, Galliker, Levine, 2025) prefill KV-кэша π0 занимает 46 мс при шаге управления 20 мс: за один вывод проходит больше двух тиков. Как стыковать пачки без пауз и рывков, разберём в уроке 1.7.

Другие системы. π0-FAST тратит на пачку около 750 мс против ~100 мс у π0: 30–60 токенов действий 2B-модель декодирует по одному. GR00T N1 (2,2B, из них 1,34B — VLM) выдаёт пачку из 16 действий за 63,9 мс на L40; VLM работает на 10 Гц, действия — на 120 Гц. В Helix медленная VLM S2 на 7B работает на 7–9 Гц, быстрая политика S1 на 80M — на 200 Гц и управляет 35 степенями свободы.

6 Модели

Как модели выдают действия

Трансформер внутри у всех, а действия выдают по-разному. Можно записать действие строкой токенов и генерировать их по одному, как текст. Можно выдать всю пачку за один проход декодера. А можно получить пачку из шума за несколько шагов диффузии или flow matching. От способа зависит, сколько проходов модели нужно на одну пачку.

🧩 Задача

Разложи модели по способу выдачи действий

Перетащи карточку в корзину или нажми карточку, а потом корзину.

Как модели превращают наблюдения и действия в токены

МодельНаблюдения → токеныДействияВнимание
Decision Transformerсостояние через линейный слой (Atari — CNN) плюс токен return-to-go1 токен на шаг, предсказывается из токена состоянияGPT, каузальная маска; K шагов — 3K токенов
RT-1, 35M6 кадров 300 × 300 → FiLM-EfficientNet-B3, язык через USE → 81 → TokenLearner → 8 на кадр, всего 4811 измерений (7 рука, 3 база, 1 режим) × 256 биновтолько декодер, 8 слоёв, 19M
RT-2, 55B / 12Bкартинка и текст через VLMстрока из 8 целых, 256 биновкак в исходной VLM
OpenVLA, 7B224 × 224, DINOv2 + SigLIP → проектор → Llama 27 измерений × 256 бинов вместо 256 редких токенов словаряавторегрессия
ACT, ~80M4 камеры 480 × 640 → ResNet18 → 300 на камеру, плюс суставы и z — 1202100 фиксированных запросов → cross-attention → 100 × 14энкодер 4 слоя, декодер 7, CVAE
Octo, 27M / 93MCNN и патчи 16 × 16: 256 (256 × 256) + 64 (запястье 128 × 128), 2 кадра; язык T5 → 16readout-токены → диффузионная голова → пачкаблочная маска; readout только читает
π0, 3,3BSigLIP: 256 на кадр (224 px, openpi); состояние → 1 токен50 токенов через action expert 300M, flow matching, 10 шагов3 блока: [картинки + текст], [состояние], [действия]
GR00T N1, 2,2B224 × 224 → SigLIP-2 и pixel shuffle → 64 на кадр; признаки 12-го слоя LLM16 действий, flow matching, 4 шагаDiT: self-attention по действиям, cross-attention к VLM
Helix, 7B + 80MS2 сжимает сцену и команду в один латентный вектор; у S1 свёрточный энкодер35 степеней свободы на 200 ГцS1 — энкодер-декодер с cross-attention
7 Проверь себя

Восемь вопросов о типичных заблуждениях

8 Итог

Итоги урока

  1. Политика превращает всё в токены: патчи картинок, слова команды, состояние, действия. Число токенов — главный рычаг стоимости.
  2. Внимание: запрос сравнивается с ключами, softmax даёт веса, ответ — смесь значений. Длина запроса задаёт резкость, а при размазанных весах ответ оказывается между вариантами.
  3. Деление на dk\sqrt{d_k} держит оценки в рабочем диапазоне: без него softmax схлопывается в один пик.
  4. Маска решает, кто кого видит. Блочная маска π0 отделяет наблюдение от действий, поэтому его можно кэшировать. Головы смотрят на разные признаки, и вместе различают то, что каждая путает.
  5. Внимание само не знает порядка: его задают позиционные кодировки.
  6. Квадратичен только член внимания. KV-кэш ускоряет вывод, а пачки отделяют частоту управления от частоты вывода: 73 мс на вывод и 50 Гц на робота.

Открытые вопросы

Хочешь добавить политике четвёртую камеру высокого разрешения. Что посчитаешь, прежде чем решить?

Сколько токенов даст камера: у PaliGemma картинка 224 / 448 / 896 px — это 256 / 1024 / 4096 токенов. Как вырастет член внимания и его доля в стоимости слоя. Сколько добавится KV-кэша и, главное, времени до первого шага flow: у π0 это уже 46 мс из 73. Уложится ли вывод в интервал между запусками пачек. И сколько будет стоить обучение: OpenVLA на 384 px вместо 224 обучалась в 3 раза дольше без прироста качества. Часто дешевле сжать токены, как TokenLearner в RT-1 или 64 токена на кадр в GR00T N1.

Почему π0 может управлять на 50 Гц, если один вывод занимает 73 мс?

Потому что модель выдаёт пачку из 50 действий, а робот исполняет 25 из них по 20 мс: модель нужна раз в 0,5 с, и 73 мс в этот интервал укладываются. Сам вывод быстрый благодаря KV-кэшу: наблюдение проходится один раз, а 10 шагов flow стоят 27 мс. Helix и GR00T идут дальше и разделяют медленную VLM (7–10 Гц) и быструю политику (120–200 Гц).

Гид по статье

A. Vaswani и соавторы, «Attention Is All You Need», NeurIPS 2017.

Материалы

➡️

Дальше: пачка действий за один проход. ACT — трансформер, который выдаёт пачку из 100 действий за один проход декодера. Почему пачки помогают, сколько действий брать и что делать на стыках — урок 1.7 «ACT», он выйдет следующим.

Урок пригодился? Скажи спасибо — так автор узнает, что курс читают.