中文翻译暂不可用,显示俄语原文。

Что такое residual stream и как он связан с информационным потоком в трансформере?

Краткий тезис

Residual stream — это непрерывный вектор, который проходит через все слои трансформера, начиная с суммы эмбеддинга токена и позиционного кодирования. Каждый слой (Multi-Head Attention и Feed-Forward) добавляет к этому вектору свой выход через skip connection (остаточное соединение). Таким образом, residual stream служит «общей магистралью» для информации: он сохраняет исходные данные, позволяет градиентам эффективно распространяться при обучении и даёт возможность каждому слою вносить лишь небольшие коррективы. Без residual stream глубокие трансформеры страдали бы от затухания градиентов и потери информации о позиции.


1. Термин: Residual stream и skip connection

Residual stream (stream|остаточный поток) — это вектор, который передаётся от входа трансформера к выходу, проходя через все слои. Формально, если обозначить входной вектор как x_0, то после l-го слоя:

x_l = x_{l-1} + F_l(x_{l-1})

где F_l — функция, вычисляемая слоем (например, Multi-Head Attention или Feed-Forward). Такая конструкция называется skip connection (пропускное соединение) или residual connection (остаточное соединение). Термин «остаточный» означает, что слой учится предсказывать остаток (разницу) между входом и желаемым выходом.

Ключевая идея: вместо того чтобы каждый слой полностью преобразовывал вход, он лишь добавляет небольшое изменение к уже существующему представлению.


2. Аналогия с магистралью

Представьте residual stream как главную магистраль данных (highway), по которой непрерывно движется вектор. Каждый слой — это «заводской цех», который может добавить к грузу (вектору) свою деталь, но не заменяет весь груз. Если цех ничего не добавляет (нулевой вклад), груз остаётся неизменным. Это гарантирует, что информация из ранних слоёв (например, позиция токена) не будет потеряна, даже если сеть очень глубокая.


3. Формирование residual stream: начало

На вход трансформера подаётся последовательность токенов. Каждый токен преобразуется в эмбеддинг (вектор фиксированной размерности d_model). Затем добавляется позиционное кодирование (positional encoding), чтобы модель знала порядок токенов. Результат — начальный residual stream:

x_0 = Embedding(token) + PositionalEncoding(position)

Этот вектор x_0 идёт в первый слой трансформера.


4. Роль residual stream в каждом слое

Каждый слой трансформера состоит из двух подуровней:

  1. Multi-Head Self-Attention (MHSA)
  2. Feed-Forward Network (FFN)

Оба подуровня используют residual connection. Схема для одного слоя:

x' = x + MHSA(LayerNorm(x))   # первый skip
x'' = x' + FFN(LayerNorm(x')) # второй skip

Здесь LayerNorm — нормализация слоя, применяемая перед вычислением функции (Pre-LN архитектура). Важно: residual stream не проходит через нормализацию — она применяется только к входу подуровня. Таким образом, residual stream остаётся «чистым» и не искажается нормализацией.

Каждый подуровень добавляет к residual stream свой выход. Поскольку размерность d_model сохраняется на всём пути, сложение возможно.


5. Преимущества residual stream

ПреимуществоОписание
Борьба с затуханием градиентовГрадиенты могут течь напрямую через skip connection, минуя умножение на веса. Это позволяет обучать очень глубокие сети (десятки слоёв).
Сохранение информацииИсходные эмбеддинги и позиционные сигналы не затираются последующими слоями. Модель может «вернуться» к ранним представлениям.
Ускорение сходимостиОстаточные соединения делают функцию отображения более гладкой, что упрощает оптимизацию.
ИнтерпретируемостьМожно анализировать, какой вклад внёс каждый слой, вычитая residual stream до и после слоя.

6. Связь с информационным потоком

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

Без residual stream каждый слой должен был бы заново «изобретать» представление, что привело бы к потере контекста и проблемам с обучением. С residual stream информация может быть избирательно добавлена или изменена, а исходные признаки (например, позиция) сохраняются на протяжении всей глубины.


7. Визуализация residual stream

Вход: [x0] → + ← выход Attention
            ↓
          [x1 = x0 + Attn(x0)]
            ↓
          + ← выход FFN
            ↓
          [x2 = x1 + FFN(x1)]  → следующий слой

Каждый + — это skip connection. Residual stream — это последовательность x0, x1, x2, .... В конце последнего слоя residual stream подаётся на выходной проекционный слой (или на голову для предсказания следующего токена).


8. Отличие от ResNet

ResNet (Residual Network) в компьютерном зрении также использует skip connections, но там residual stream часто называют «identity mapping» (тождественное отображение). В трансформерах концепция аналогична, но есть нюансы:

  • В ResNet skip connection может быть проекцией (если размерность меняется), в трансформерах размерность d_model фиксирована, поэтому сложение всегда возможно.
  • В трансформерах residual stream дополнительно нормализуется через LayerNorm перед каждым подуровнем (Pre-LN), что улучшает стабильность обучения.

9. Влияние на интерпретируемость

Residual stream позволяет исследовать, какую информацию добавляет каждый слой. Например, можно вычислить разность x_l - x_{l-1} и проанализировать, какие признаки (синтаксические, семантические) активируются на разных глубинах. Это используется в работах по механистической интерпретируемости (mechanistic interpretability) трансформеров.


10. Практические аспекты: Pre-LN vs Post-LN

В оригинальной статье «Attention is All You Need» использовалась Post-LN (нормализация после сложения):

x' = LayerNorm(x + MHSA(x))

Однако на практике Pre-LN (нормализация перед сложением) оказалась стабильнее для глубоких сетей:

x' = x + MHSA(LayerNorm(x))

В Pre-LN residual stream не проходит через LayerNorm, что сохраняет его «чистым» и облегчает поток градиентов. Большинство современных трансформеров (GPT, BERT, LLaMA) используют Pre-LN.


Пет-проект для закрепления

Задача Реализовать минимальный трансформер с одним слоем и визуализировать residual stream.

Инструменты Python, PyTorch, matplotlib.

Шаги:

  1. Создайте класс SimpleTransformerBlock с MHSA и FFN, используя Pre-LN и residual connections.
  2. Сгенерируйте случайный входной тензор x формы (batch, seq_len, d_model).
  3. Прогоните через блок и сохраните x до и после каждого подуровня.
  4. Вычислите разности delta_attn = x_after_attn - x_before_attn и delta_ffn = x_after_ffn - x_after_attn.
  5. Визуализируйте нормы этих разностей по токенам — вы увидите, что вклад каждого подуровня относительно невелик по сравнению с самим residual stream.

Ожидаемый результат Вы убедитесь, что residual stream остаётся доминирующим, а добавки слоёв — это малые коррекции. Это подтверждает концепцию «магистрали».


Связь с другими вопросами

ВопросТема
675Что такое Multi-Head Attention и как он работает?
677Как устроен Feed-Forward слой в трансформере?
678Зачем нужна Layer Normalisation и как она применяется?
679Как работает позиционное кодирование?
680Что такое skip connection и почему он важен для глубоких сетей?
681Как обучать глубокие трансформеры без затухания градиентов?

Навигация