Все статьи
Артемий Мазаев·· 7 мин чтения

Позиционное кодирование: RoPE, YaRN и почему Inkling от них отказался 🎡📐

Зачем трансформеру позиция, как RoPE поворачивает векторы на угол m·θ, почему это относительное кодирование, где оно ломается на длинном контексте и как чинят (NTK, YaRN) — плюс контртезис: Thinking Machines в Inkling выкинула RoPE. С пятью визуальными демками механики.

Позиционное кодирование: RoPE, YaRN и почему Inkling от них отказался 🎡📐

Ну чё, малютки, в июле 2026 Thinking Machines выпустила Inkling и мимоходом сделала то, чего фронтир не делал с 2023-го: выкинула RoPE. Дословно — «relative positional embedding работает лучше и лучше экстраполируется на длинные последовательности, чем более распространённый Rotary Positional Embedding». Чтобы понять, почему это новость, надо понять, что вообще делает RoPE — и почему трансформеру без позиционного кодирования всё равно, в каком порядке идут токены. Разбираем механику от начала до конца, с визуальными демками: RoPE — это буквально вращение векторов, и его удобнее один раз увидеть, чем прочитать десять формул.

🔥Суть за 10 секунд

Self-attention перестановочно-инвариантен — сам по себе он не различает порядок токенов, позицию надо впрыснуть отдельно. RoPE делает это поворотом: вектор на позиции m поворачивается на угол m·θ, причём разные пары измерений вращаются с разными частотами. Красота в том, что скалярное произведение зависит только от разности позиций (m−n) — то есть кодирование относительное. Ломается RoPE за длиной обучения: углы уходят out-of-distribution. Чинят интерполяцией позиций — NTK-aware и YaRN. А Inkling утверждает, что относительное смещение вместо RoPE экстраполируется лучше.


Часть 1: Зачем трансформеру вообще позиция

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

🔀 Attention без позиции не видит порядок
Жми «перемешать». Сверху — «без позиции»: агрегат (сумма) не меняется от порядка. Снизу — «с позицией»: каждый токен помечен индексом, порядок различим.
Без позиционного кодирования
ловитночьюмышькот
Σ = 14 — тот же результат при любом порядке (порядок потерян)
С позиционным кодированием
ловит#0ночью#1мышь#2кот#3
Каждый токен знает свою позицию #i — порядок восстановим
Self-attention сам по себе — функция от множества токенов, не от последовательности: переставь вход, и выход переставится так же, но содержательно не изменится. Позицию нужно впрыснуть отдельно. RoPE — один из способов.

Исторически было два лагеря. Абсолютное кодирование — приклеить к каждому токену вектор его позиции: синусоиды из оригинального «Attention Is All You Need» или обучаемые эмбеддинги позиций. Относительное — кодировать не «токен на позиции 5», а «токен на 3 позиции левее». RoPE хитро совмещает удобство первого с семантикой второго.


Часть 2: RoPE как поворот

Идея RoPE (Su et al., «RoFormer», arXiv:2104.09864) — не прибавлять позицию к вектору, а поворачивать сам вектор запроса и ключа на угол, пропорциональный позиции. Измерения берутся парами (2i, 2i+1), и каждая пара вращается как точка на плоскости. Для одной пары на позиции m:

f{q,k}(xm,m)=(cosmθsinmθsinmθcosmθ)(xm(1)xm(2))f_{\{q,k\}}(x_m, m) = \begin{pmatrix} \cos m\theta & -\sin m\theta \\ \sin m\theta & \cos m\theta \end{pmatrix} \begin{pmatrix} x_m^{(1)} \\ x_m^{(2)} \end{pmatrix}

Целиком по всем измерениям это блочно-диагональная матрица поворота RΘ,mdR^d_{\Theta,m}, где i-я пара крутится со своей частотой:

θi=100002i/d,i[0,d/21]\theta_i = 10000^{-2i/d}, \quad i \in [0, d/2 - 1]

(в пейпере эта же величина написана и в 1-индексной форме 100002(i1)/d10000^{-2(i-1)/d} — это тот же набор частот, просто другая нумерация). База 10000 — та же, что в синусоидах оригинального трансформера.

🎡 RoPE: поворот вектора на угол m·θ
Каждая пара измерений вращается со своей частотой θ. Двигай позицию m — низкие измерения (высокая частота) крутятся быстро, высокие (низкая частота) едва ползут. Иллюстративно, d=8.
пара 0
θ=1
98°
пара 1
θ=0.1
46°
пара 2
θ=0.01
5°
пара 3
θ=0.001
0°
позиция m8
Угол пары i на позиции m равен m·θ_i, где θ_i = 10000^(−2i/d) (RoFormer, arXiv:2104.09864). Разброс частот по измерениям и есть то, что позже назовут «длинами волн» RoPE — от коротких к длинным.

Низкие измерения (маленькое i, θ близко к 1) вращаются быстро — полный оборот за считанные позиции. Высокие (большое i, θ крошечное) едва ползут — им нужны тысячи позиций на оборот.


Часть 3: Почему это относительное кодирование

Вот главный трюк. Хотя RoPE задаётся через абсолютную позицию m, скалярное произведение повёрнутого запроса и повёрнутого ключа зависит только от разности позиций:

fq(xm,m),fk(xn,n)=g(xm,xn,mn)\langle f_q(x_m, m),\, f_k(x_n, n) \rangle = g(x_m, x_n, m - n)

(RoFormer, уравнение 11). Поворот на m и поворот на n при перемножении дают поворот на (m−n) — абсолютные углы сокращаются, остаётся относительный. То есть attention через RoPE видит «на сколько позиций один токен отстоит от другого», а не «какой у каждого абсолютный индекс».

🧭 Важна разность фаз, а не абсолютные позиции
Запрос на позиции m (фиолетовый) и ключ на позиции n (синий). Скалярное произведение RoPE зависит только от угла между ними — то есть от (m−n). Сдвинь m и n на одинаковую величину — разность не изменится.
запрос m7
ключ n3
Разность фаз = (m−n)·θ = (73)·θ → 80°. Именно от неё зависит dot-product, не от m и n по отдельности.
Формально: ⟨f_q(x_m, m), f_k(x_n, n)⟩ = g(x_m, x_n, m−n) (RoFormer, Eq. 11) — внутреннее произведение зависит только от относительного сдвига m−n. Поэтому RoPE — относительное кодирование, хоть и задаётся через абсолютную позицию.

А разброс частот по измерениям (из Части 2) означает, что RoPE кодирует относительные расстояния сразу на многих масштабах — от «соседний токен» до «за тысячу позиций». Само слово «длина волны» для этих измерений закрепил позже пейпер YaRN; RoFormer называл это «long-term decay».

🌈 Длины волн по измерениям (лог-масштаб)
Длина волны пары i — сколько позиций нужно на полный оборот: λ = 2π/θ. Низкие измерения крутятся часто (короткая волна), высокие — редко (длинная). Иллюстративно, d=16.
пара 0
6.3
пара 1
19.9
пара 2
62.8
пара 3
199
пара 4
628
пара 5
1 987
пара 6
6 283
пара 7
19 869
← высокая частота (близкие позиции)низкая частота (далёкие) →
Именно этот разброс масштабов даёт RoPE и близкие, и далёкие относительные расстояния сразу. Само слово «длина волны» для этих измерений закрепил пейпер YaRN (arXiv:2309.00071) — RoFormer называл это «long-term decay».

Всё это — про углы векторов. А зачем угол вообще влияет на ответ? Attention выбирает тот ключ, к которому запрос ближе по направлению: поверни вектор запроса — и на выход выходит другое слово. Пощупай сам:

🎯 Поверни запрос — сменится выходное слово
Пять слов-ключей смотрят в разные стороны. Фиолетовый вектор — запрос. Крути его: чем он ближе по направлению к слову, тем выше внимание к нему, и то слово выходит на выход. Иллюстративно, 2D, одна голова.
котловитмышьспитднём
Выходное слово (максимум внимания)
кот
кот
87%
ловит
6%
мышь
0%
спит
0%
днём
6%
поверни запрос30°
Внимание тут — softmax по косинусу угла между запросом и ключами (в реальных моделях — по скалярному произведению q·k в многомерном пространстве). Поворот вектора меняет эти углы, а значит и то, какой токен выигрывает. Именно поэтому позиция, закодированная как поворот (RoPE), напрямую влияет на то, что модель достаёт на выход.

Часть 4: Где RoPE ломается и как чинят

Проблема вылезает, когда на инференсе последовательность длиннее, чем всё, что модель видела при обучении. Пусть при обучении позиции доходили до L_train. Тогда для каждой пары измерений модель видела углы только в диапазоне [0, θ·L_train]. На позиции m > L_train угол m·θ уходит за этот диапазон — в область, которой при обучении не было. Модель получает паттерн вращения, на который её не учили, и качество сыпется.

💥 Экстраполяция ломается — и как её чинят
Зелёная дуга — углы, которые модель видела при обучении (позиции 0…32). Двигай m за 32: без патча стрелка уходит за дугу (OOD, красным). Включи интерполяцию позиций — позиция сжимается обратно в обученный диапазон. Иллюстративно, θ=0.05.
позиция m64
m=64 > L_train — угол вне обученной дуги, out-of-distribution ✗
Простейший фикс — Position Interpolation (Chen, arXiv:2306.15595): позиция m отображается в m·L/L′, возвращаясь в обученный диапазон (LLaMA растянули до 32768 за <1000 шагов дообучения). NTK-aware (community, bloc97) и YaRN (arXiv:2309.00071) делают это умнее — растягивают низкие частоты сильнее высоких (b′ = b·s^(|D|/(|D|−2))), плюс YaRN добавляет температуру внимания √(1/t) = 0.1·ln(s)+1.

Чинят это интерполяцией позиций, и есть три уровня хитрости:

  • Position Interpolation (Chen et al., arXiv:2306.15595) — в лоб: отобразить позицию m в mL/Lm \cdot L/L', линейно сжав весь диапазон обратно в обученный. Так LLaMA растянули с 2048 до 32768 контекста меньше чем за 1000 шагов дообучения.
  • NTK-aware interpolation — придумано в community-посте (bloc97, r/LocalLLaMA, середина 2023, потом зафиксировано в пейпере YaRN): вместо равномерного сжатия всех частот масштабируют базу неравномерно — b=bsD/(D2)b' = b \cdot s^{|D|/(|D|-2)}, где s — коэффициент расширения. Высокие частоты почти не трогают, низкие растягивают. Меньше портит близкие расстояния.
  • YaRN (Peng et al., arXiv:2309.00071) — «NTK-by-parts» (интерполировать по-разному в зависимости от длины волны измерения) плюс температурный трюк на внимании: домножить логиты так, чтобы 1/t=0.1ln(s)+1\sqrt{1/t} = 0.1 \ln(s) + 1. YaRN расширяет контекст до 128k, требуя, по заявлению авторов, «в 10 раз меньше токенов и в 2.5 раза меньше шагов обучения», чем прежние методы.

Часть 5: Контртезис Inkling

И вот тут возвращаемся к началу. Thinking Machines в Inkling (июль 2026) решила, что вся эта конструкция — вращение плюс патчи на экстраполяцию — не оптимальна, и заменила RoPE на relative positional embedding (по формулировке анонса; «выученное» — это уже наша интерпретация, дословно они говорят просто «relative positional embedding»). Их заявление: оно «работает лучше и экстраполируется лучше на длинные последовательности, чем более распространённый RoPE».

Плюс — деталь, которая тут неслучайна: Inkling добавляет короткие свёртки в двух местах — после проекций key и value в каждом слое внимания и на residual-ветках внимания и MLP. Свёртка по своей природе кодирует локальный порядок соседних токенов — то есть часть работы позиционного кодирования уходит в неё.

Насколько это лучше RoPE на практике — покажут независимые замеры (Inkling — свежая модель: 975B параметров всего / 41B активных, MoE из 256 роутизируемых + 2 shared экспертов, sliding-window и global attention в пропорции 5:1, контекст до 1M, 45 триллионов мультимодальных токенов претрейна). Но сам факт, что фронтир-лаборатория ставит под сомнение стандарт де-факто трёх последних лет, — уже сигнал, что позиционное кодирование не «решённая» тема.


TL;DR

1Зачем: self-attention перестановочно-инвариантен — без позиционного кодирования не различает порядок токенов
2RoPE (RoFormer, arXiv:2104.09864): поворот вектора на угол m·θ, пары измерений вращаются с частотами θ_i = 10000^(−2i/d) — низкие измерения быстро, высокие медленно
3Относительность: ⟨f_q(x_m,m), f_k(x_n,n)⟩ = g(x_m,x_n,m−n) — dot-product зависит только от разности позиций, хоть RoPE и задан через абсолютную
4Ломается за длиной обучения: углы m·θ уходят out-of-distribution. Чинят интерполяцией: Position Interpolation (m→m·L/L′), NTK-aware (масштаб базы b′=b·s^(|D|/(|D|−2))), YaRN (+ температура √(1/t)=0.1·ln(s)+1, до 128k)
5Inkling (Thinking Machines, июль 2026): выкинула RoPE ради relative positional embedding + коротких свёрток, заявляя лучшую экстраполяцию — фронтир ставит под сомнение стандарт де-факто

RoPE — красивая идея: закодировать относительную позицию через абсолютный поворот, бесплатно получив свойство m−n. Но «бесплатно» кончается ровно на границе длины обучения, и всё, что дальше — интерполяционные костыли той или иной степени изящества. Inkling предлагает не чинить, а заменить. Кто прав — узнаем по независимым длинноконтекстным замерам, а не по строчке в анонсе. 🫡


Источники

  1. RoFormer: Enhanced Transformer with Rotary Position Embedding — Su et al. (arXiv:2104.09864)
  2. Extending Context Window of LLMs via Positional Interpolation — Chen et al. (arXiv:2306.15595)
  3. YaRN: Efficient Context Window Extension of Large Language Models — Peng et al. (arXiv:2309.00071)
  4. Train Short, Test Long: Attention with Linear Biases (ALiBi) — Press et al. (arXiv:2108.12409)
  5. Introducing Inkling — Thinking Machines Lab
  6. KV-кэш: почему LLM помнит без памяти и жрёт VRAM
  7. FlashAttention: как реально считается attention на GPU
  8. Kimi K3: open-weight модель обгоняет Claude Opus 4.8