Attention

Self-attention — механизм, которым каждый токен «смотрит» на все остальные и собирает релевантную информацию. Сердце Transformer: заменил рекуррентность (RNN/LSTM), дал параллелизм и прямую связь далёких токенов.

Суть

Для каждого токена считаются три вектора (умножением его эмбеддинга на обучаемые матрицы W_Q, W_K, W_V):

  • Q (Query) — «что я ищу?»
  • K (Key) — «что я предлагаю?»
  • V (Value) — «что я отдаю?»

Формула: Attention(Q, K, V) = softmax(Q·Kᵀ / √d) · V.

Зачем это нужно

Attention позволяет токену контекстно зависеть от любого другого токена напрямую (а не через цепочку шагов, как в RNN) и считать это для всех токенов параллельно одним матричным умножением. Отсюда — масштабируемость трансформеров.

Как работает

  1. Скалярные произведения Q каждого токена с K всех остальных → «насколько релевантен».
  2. Делим на √d (стабильность), применяем softmax → веса важности.
  3. Взвешенная сумма V-векторов по этим весам → новое представление токена.
  • Causal mask (decoder, GPT/Claude): токен N видит только 0..N; «будущее» заменяется на −∞ перед softmax (см. Encoder vs Decoder).
  • Multi-Head Attention: вместо одной — несколько голов (8–96), каждая в своём подпространстве (d_model / num_heads), со своими Q/K/V; результаты конкатенируются через W_O. Головы сами специализируются: previous-token, punctuation, coreference, induction heads (реализуют in-context learning).
  • GQA (Grouped Query Attention): Q-голов больше, чем K/V-голов → экономия памяти KV Cache.
  • Сложность квадратична по длине → дорогой длинный контекст (см. Context Window).

Пример

Q·Kᵀ  →  /√d  →  softmax  →  веса × V  →  контекстный вектор токена

Flash Attention и sparse attention: что именно они меняют

Эти два приёма часто ставят в один ряд, хотя они решают разные проблемы, и путаница здесь стоит неверных ожиданий.

Flash Attention асимптотику вычислений не меняет — она остаётся квадратичной по длине последовательности. Меняется потребление памяти: матрица внимания целиком не материализуется, вычисление идёт блоками с пересчётом там, где иначе понадобилось бы хранить промежуточный результат. Память из квадратичной становится линейной, а скорость растёт не за счёт меньшего числа операций, а за счёт того, что данные перестают ходить туда-сюда между быстрой и медленной памятью GPU. Практический эффект: длинный контекст перестаёт упираться в память, при том же железе.

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

Отсюда практический вывод: Flash Attention — это оптимизация без компромисса, её берут всегда, когда она доступна; sparse attention — размен качества на длину, и он требует проверки на своей задаче.

Связано с

  • Transformer — attention как ядро блока
  • Embeddings — из них получаются Q/K/V
  • KV Cache — кэширование K/V при генерации; GQA уменьшает его
  • Context Window — квадратичная сложность attention