Позиционные кодировки: зачем модели порядок (запускаемый пример)

«Кот поймал мышь» и «Мышь поймала кота» состоят из одних слов, но смысл разный. Этот урок — про то, как модель узнаёт порядок токенов.

Позиционная кодировка — это добавляемая к эмбеддингу токена информация о его месте в последовательности, без которой модель не различала бы порядок слов.

Внимание само по себе слепо к порядку

Заглянем чуть вперёд: механизм внимания (раздел 3) обрабатывает токены как множество, а не как упорядоченный список. Он смотрит, какие токены на какие похожи, но «не знает», какой шёл первым. Если бы мы просто перемешали слова, для голого внимания почти ничего бы не изменилось. А для языка порядок критичен: подлежащее и дополнение, отрицание, время — всё держится на позициях.

Решение: добавить позицию в вектор

Раз сам механизм порядок не видит, информацию о позиции вшивают прямо в векторы. К эмбеддингу каждого токена прибавляют (или присоединяют) вектор, зависящий от его позиции. Тогда «кот на позиции 1» и «кот на позиции 5» приходят в слой внимания уже разными — и модель может учитывать порядок.

Синусоидальные кодировки

В оригинальном трансформере позицию кодировали набором синусов и косинусов разной частоты. Для позиции pos и измерения i: чётные измерения — синус, нечётные — косинус, а частота плавно меняется по измерениям. Посчитаем такие векторы для первых позиций.

import math

# Синусоидальные позиционные кодировки (как в оригинальном трансформере).
# Для позиции pos и измерения i: чётные -> sin, нечётные -> cos.
d_model = 4  # размерность вектора

def positional_encoding(pos, d_model):
    pe = []
    for i in range(d_model):
        k = i // 2
        angle = pos / (10000 ** (2 * k / d_model))
        pe.append(math.sin(angle) if i % 2 == 0 else math.cos(angle))
    return pe

for pos in range(4):
    vec = positional_encoding(pos, d_model)
    nums = ", ".join(f"{v:+.3f}" for v in vec)
    print(f"позиция {pos}: [{nums}]")

Вывод:

позиция 0: [+0.000, +1.000, +0.000, +1.000]
позиция 1: [+0.841, +0.540, +0.010, +1.000]
позиция 2: [+0.909, -0.416, +0.020, +1.000]
позиция 3: [+0.141, -0.990, +0.030, +1.000]

Заметьте: у каждой позиции получается свой уникальный узор из чисел. Низкие измерения меняются быстро (различают соседние позиции), высокие — медленно (различают далёкие). Такая схема позволяет модели судить и об абсолютной позиции, и об относительных расстояниях между токенами — и работает даже для последовательностей длиннее тех, что встречались при обучении.

Современные варианты

Синусоиды — классика, но не единственный способ:

ПодходИдея
Синусоидальныефиксированные синусы/косинусы, добавляются к эмбеддингу
Обучаемыевектор позиции — обучаемый параметр, как эмбеддинг
Относительные / RoPEкодируют расстояние между токенами; помогают с длинным контекстом

Современные большие модели чаще используют относительные кодировки (например, RoPE) — они лучше переносятся на длинные тексты. Но идея одна: без явной информации о позиции внимание было бы слепо к порядку слов.

Итог

  • Механизм внимания сам по себе не различает порядок токенов — для него это множество.
  • Позиционные кодировки вшивают информацию о месте токена прямо в его вектор.
  • Синусоидальные кодировки дают каждой позиции уникальный узор разных частот.
  • Современные модели часто применяют относительные кодировки (RoPE) для длинного контекста.
Проверьте себя
1. Почему механизму внимания нужны позиционные кодировки?
AЧтобы ускорить вычисления
BСам по себе он обрабатывает токены как множество и не различает их порядок
CЧтобы уменьшить размер модели
DЧтобы экономить память
2. Как позиционная кодировка попадает в модель?
AХранится в отдельной базе данных
BДобавляется (или присоединяется) к эмбеддингу токена, делая его зависимым от позиции
CПередаётся пользователем вручную
DВычисляется после генерации
3. Чем RoPE и относительные кодировки полезнее простых обучаемых?
AОни вообще не нужны современным моделям
BКодируют расстояние между токенами и лучше переносятся на длинный контекст
CОни делают модель меньше
DОни убирают необходимость в эмбеддингах
Поддержать проект