Архитектура трансформер: из чего собран Transformer

Архитектура трансформер (Transformer) - это нейросеть из 2017 года, которая полностью отказалась от рекуррентности и свёрток и собрала обработку последовательности на одном механизме: внимании. Сегодня на ней построены почти все большие языковые модели, и понимать её устройство нужно и на собеседовании, и в курсовой по глубокому обучению. Ниже разберём архитектуру по кирпичам: чем энкодер отличается от декодера, что внутри одного блока, как данные проходят насквозь и зачем каждому подслою нужны residual-связь и нормализация. Чтобы сразу увидеть, как меняется размер сети при разном числе слоёв и голов, соберите свой расчёт в инструменте ниже.
Что такое трансформер и зачем он появился
До трансформера последовательности обрабатывали рекуррентные сети (RNN, LSTM): скрытое состояние передавалось от токена к токену по цепочке. Это создавало два узких места - сигнал между далёкими словами размывался по пути, а вычисления нельзя было распараллелить, потому что сотый токен зависел от девяносто девятого. Статья «Attention Is All You Need» предложила убрать рекуррентность целиком и связать любые две позиции последовательности напрямую - через механизм внимания attention.
Получилась архитектура, где каждый слой видит всю последовательность сразу. Это дало два эффекта: путь между любой парой токенов стал равен единице (дальние зависимости больше не теряются), а все позиции считаются параллельно как одно перемножение матриц, идеально ложащееся на GPU. Именно поэтому трансформеры удалось масштабировать до миллиардов параметров - обучение перестало быть последовательным.

Энкодер и декодер: две половины
В оригинальной архитектуре трансформер состоит из двух стеков - энкодера и декодера, по одинаковых блоков в каждом.
Энкодер читает весь вход целиком и строит его контекстное представление. Каждый его блок содержит два подслоя: multi-head self-attention (токены смотрят друг на друга без ограничений) и позиционный полносвязный слой (FFN). Внимание здесь двунаправленное - слово видит и левых, и правых соседей.
Декодер генерирует выход по одному токену и содержит уже три подслоя: маскированное self-attention (чтобы при генерации позиция не подсматривала будущие токены), cross-attention (через него декодер «читает» выход энкодера) и тот же FFN. Маска - это добавление в матрицу весов справа от текущей позиции, чтобы после softmax они занулились.
На этой схеме держатся три семейства моделей. Чисто энкодерные (BERT) хороши для понимания текста, чисто декодерные (GPT) - для генерации, полные энкодер-декодеры (T5, оригинальный Transformer) - для перевода и задач «вход → выход».

Multi-head self-attention внутри блока
Сердце каждого блока - внимание с несколькими головами. Базовый расчёт - scaled dot-product: из входа линейными проекциями получают запросы, ключи и значения, а затем взвешивают значения по сходству запросов и ключей:
Масштаб обязателен: без него при больших скалярные произведения раздуваются, softmax вырождается в почти one-hot, и градиент перестаёт течь. Подробнее механика одного слоя разобрана в материале про self-attention механизм.
«Multi-head» означает, что этот расчёт делают параллельно раз с разными проекциями, а результаты склеивают:
где каждая работает в подпространстве размерности . Зачем несколько голов? Каждая учится своему типу связи: одна ловит синтаксис (подлежащее - сказуемое), другая кореференцию (местоимение - его антецедент), третья позиционную близость. Одна голова усреднила бы всё в одну размытую связь.
Позиционное кодирование
У self-attention есть неочевидное свойство: он инвариантен к перестановке токенов. В формуле нет ни одного слагаемого, зависящего от того, где стоит токен, - переставьте слова, и выходные векторы просто переставятся, не изменив содержимого. Для модели «собака укусила человека» и «человека укусила собака» без дополнительной информации одинаковы.
Поэтому к эмбеддингам перед первым блоком добавляют позиционное кодирование - вектор, кодирующий номер позиции:
Синусоиды разной частоты дают каждой позиции уникальную «подпись», а относительные сдвиги выражаются линейно - модель легко улавливает «на две позиции левее». Современные модели чаще используют обучаемые или вращательные кодировки RoPE, но идея та же: вернуть слою чувство порядка. Пропустить этот шаг - классическая ошибка реализации с нуля.
FFN, residual и нормализация
Между блоками внимания стоит позиционный FFN - два линейных слоя с нелинейностью, применяемые к каждой позиции независимо:
Внутренняя размерность обычно вчетверо больше: . Если внимание перемешивает информацию между токенами, то FFN нелинейно перерабатывает её внутри каждой позиции - это основной «склад» знаний модели по числу параметров.
Каждый из подслоёв обёрнут в два приёма, без которых глубокая сеть не обучилась бы. Residual-связь пропускает вход в обход подслоя - это даёт градиенту короткий путь и спасает от затухания при десятках слоёв. LayerNorm нормирует активации по признакам, удерживая их в стабильном масштабе. Вместе они образуют шаблон (post-norm в оригинале; в современных моделях чаще pre-norm - норма до подслоя, она устойчивее при обучении).
Как данные проходят насквозь
Соберём путь одного входа в энкодере по шагам:
- Токены превращаются в эмбеддинги размерности (в оригинале 512).
- К ним прибавляется позиционное кодирование .
- Multi-head self-attention пересобирает каждый вектор из контекста; результат идёт через residual и LayerNorm.
- FFN нелинейно перерабатывает каждую позицию; снова residual и LayerNorm.
- Шаги 3–4 повторяются раз - это и есть «стек блоков».
В декодере добавляется маскированное внимание в начале и cross-attention в середине, а на самом верху - линейная проекция в словарь и softmax, дающий распределение вероятностей следующего токена. Платой за всю эту мощь служит квадратичная сложность: матрица имеет размер , поэтому память и время растут как по длине последовательности - именно этот квадрат ограничивает длину контекстного окна.
Частые ошибки
- Путать энкодер и декодер. Энкодер видит весь вход двунаправленно, декодер маскирует будущее и читает энкодер через cross-attention. BERT - энкодер, GPT - декодер.
- Забыть позиционное кодирование. Без него трансформер инвариантен к перестановке и теряет порядок слов. Добавлять нужно до первого блока.
- Игнорировать масштаб . Без него softmax насыщается и градиент перестаёт течь.
- Считать, что головы независимы и взаимозаменяемы. Каждая учится своей роли; одна голова на работает заметно хуже, чем голов меньшей размерности.
- Недооценивать . Длинный контекст в наивной реализации упирается в квадратичную память задолго до конца точности - отсюда FlashAttention и разреженное внимание.
FAQ
Чем энкодер трансформера отличается от декодера? Энкодер строит контекстное представление входа и использует двунаправленное self-attention - каждый токен видит всех соседей. Декодер генерирует выход по одному токену, поэтому его self-attention маскировано (нельзя смотреть в будущее), и в нём есть дополнительный cross-attention к выходу энкодера. Поэтому декодерный блок содержит три подслоя, а энкодерный - два.
Зачем в трансформере несколько голов внимания? Одна голова усреднила бы все типы связей в одну размытую матрицу. Несколько голов работают в разных подпространствах и параллельно ловят разные зависимости: синтаксические, кореферентные, позиционные. Затраты те же, потому что размерность каждой головы равна , а выходы склеиваются обратно.
Почему трансформер обучается быстрее RNN? RNN обрабатывает токены строго по порядку - сотый зависит от девяносто девятого, распараллелить нельзя. Трансформер считает все позиции одновременно одним перемножением матриц, что идеально ложится на GPU, а путь между любыми двумя токенами равен единице, поэтому дальние зависимости не размываются.
Коротко
Архитектура трансформер собрана из стека одинаковых блоков, где каждый держится на multi-head self-attention и позиционном FFN, обёрнутых в residual-связь и LayerNorm. Энкодер двунаправленно кодирует вход, декодер маскированно генерирует выход и читает энкодер через cross-attention. Порядок слов возвращает позиционное кодирование, добавляемое к эмбеддингам перед первым блоком. Отказ от рекуррентности дал прямой путь между любыми токенами и полный параллелизм, а ценой стала квадратичная по длине сложность .
Читайте также

Self-attention механизм: как токен смотрит на контекст
Self-attention механизм простыми словами: почему Q, K, V берутся из одной последовательности, как слой собирает контекст для каждого токена, зачем позиционное кодирование и где ошибаются.

Механизм внимания attention: формула и примеры
Механизм внимания attention: как работает scaled dot-product attention, формула softmax(QK^T/sqrt(d_k))V, матрица весов, multi-head и где чаще всего ошибаются.

Абстрактный класс и интерфейс: в чём отличие
Абстрактный класс и интерфейс: чем отличаются в ООП, когда наследовать поведение, а когда задавать контракт, как выбрать на примерах Java, C# и Python.