Недавно мы публиковали небольшой обзор статьи “Scaling Laws of RoPE-based Extrapolation”. Самое время вспомнить о базе по этой теме — сделали выжимку статьи “RoFormer: Enhanced Transformer with Rotary Position Embedding”. Это её первая часть.
Как❓
C помощью векторов query и key: мы пытаемся повернуть их так, чтобы эмбеддинги соседних токенов оказались рядом в векторном пространстве, а далёких — наоборот. Это увеличит внимание на близкие токены и понизит на дальние.
Почему❓
Потому что SDPA (Scaled Dot Product Attention), куда мы подаём вектора q и k после поворота, тем больше, чем ближе вектора, которые мы перемножаем. Это же знакомое со школьной скамьи скалярное перемножение!
Как будем поворачивать❓
Для каждого токена входной последовательности рассчитываем угол, на которых хотим повернуть эмбеддинг. Чем больше позиция слова, тем больше угол поворота — напомним, что он линейно зависит от номера позиции токена. Так токены, которые стоят в предложении рядом, оказываются близко в векторном пространстве, а далёкие, например, первое и последнее слово в предложении — далеко.
Но у эмбеддингов большая размерность, как поворачивать-то❓
А вот так: раз мы умеем решать задачу для двумерных эмбеддингов, то постараемся свести задачу с многомерными к ней же. Разобьём наш эмбеддинг размера 512 на пары координат: (x1, x2), (x3, x4), ... Затем повернём каждую пару отдельно и снова сконкатенируем в эмбеддинг нужной нам длины.
То есть, для слова с позицией m1 мы:
- (x1, x2) повернём на угол m1 * k1
- (x3, x4) повернём на угол m1 * k2
- ....
Для слова с позицией m2 мы:
- (x1, x2) повернём на угол m2 * k1
- (x3, x4) повернём на угол m2 * k2
- ....
Короче, мы поворачиваем пару координат эмбеддинги на угол, пропорциональный позиции слова в последовательности и напрямую зависящие от номера этой пары координат.
RoPE — Rotary Position Embeddings, идея добавить в механизм внимания трансформера информации о позиции слова в тексте.
Как❓
C помощью векторов query и key: мы пытаемся повернуть их так, чтобы эмбеддинги соседних токенов оказались рядом в векторном пространстве, а далёких — наоборот. Это увеличит внимание на близкие токены и понизит на дальние.
Почему❓
Потому что SDPA (Scaled Dot Product Attention), куда мы подаём вектора q и k после поворота, тем больше, чем ближе вектора, которые мы перемножаем. Это же знакомое со школьной скамьи скалярное перемножение!
Как будем поворачивать❓
Для каждого токена входной последовательности рассчитываем угол, на которых хотим повернуть эмбеддинг. Чем больше позиция слова, тем больше угол поворота — напомним, что он линейно зависит от номера позиции токена. Так токены, которые стоят в предложении рядом, оказываются близко в векторном пространстве, а далёкие, например, первое и последнее слово в предложении — далеко.
Но у эмбеддингов большая размерность, как поворачивать-то❓
А вот так: раз мы умеем решать задачу для двумерных эмбеддингов, то постараемся свести задачу с многомерными к ней же. Разобьём наш эмбеддинг размера 512 на пары координат: (x1, x2), (x3, x4), ... Затем повернём каждую пару отдельно и снова сконкатенируем в эмбеддинг нужной нам длины.
Но! Разные пары координат мы будем поворачивать на разные углы, а вернее, будем крутить с разной частотой.
То есть, для слова с позицией m1 мы:
- (x1, x2) повернём на угол m1 * k1
- (x3, x4) повернём на угол m1 * k2
- ....
Для слова с позицией m2 мы:
- (x1, x2) повернём на угол m2 * k1
- (x3, x4) повернём на угол m2 * k2
- ....
Короче, мы поворачиваем пару координат эмбеддинги на угол, пропорциональный позиции слова в последовательности и напрямую зависящие от номера этой пары координат.