English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

гость
1 / ?
назад к урокам

Внимание плюс MLP, повторяемые

Структура блока трансформера Pre-Norm


Два подслой

Блок трансформера содержит ровно два подслой, каждый из которых работает с последовательностью токенов формы [batch, seq_len, d_model]:


1. Подслой с много-головым вниманием. Токены смотрят друг на друга. Активность 68 подробно это рассматривала. Форма выхода совпадает с формой входа.

2. Подслой с прямым проходом MLP. Каждый токен трансформируется независимо через двухслойный персептрон. Нет потока информации между токенами. Форма выхода совпадает с формой входа.


Оба подслой сохраняют форму [batch, seq_len, d_model]. Это сохранение позволяет stacking блоков: выход слоя N подается на вход слоя N+1 без акробатики с формами.


Что вносит каждый подслой

Attention перемещает информацию между позициями: токен в позиции 17 может взять информацию из позиций 1 через 16. MLP трансформирует информацию внутри каждой позиции: представление токена перестраивается через выученные нелинейные функции, но никогда не видит своих соседей.


Наложение блоков чередует эти две операции. Внимание слоя 1 смешивает позиции. MLP слоя 1 перестраивает для каждой позиции. Внимание слоя 2 снова смешивает, теперь над перестроенными представлениями. Это чередование увеличивает выразительную мощь с глубиной.


Стек ANDREA


Вариантn_layern_headd_modelmlp_dim
ANDREA-12M6123841536
ANDREA-120M12127683072
ANDREA-480M162415366144

Обратите внимание, что mlp_dim = 4 × d_model во всей семье. Это соотношение сохраняется почти во всех современных трансформерах. Раздел 3 объясняет, почему так.

Назови подслои

Блок трансформера содержит два подслоя. Назови их по порядку, и для каждого укажи, перемещает ли он информацию между позициями (от токена к токену) или преобразует информацию внутри одной позиции (независимо для каждого токена). Одно предложение на подслой.

Почему важны пропуски соединений

Остаточный паттерн

Каждый подслой оборачивает свои вычисления в остаточное соединение. Выход добавляет обратно вход:


x = x + Attention(LayerNorm(x))     # подслой внимания
x = x + MLP(LayerNorm(x))           # Подслой MLP

Внутри каждого подслоя функция Attention(...) или MLP(...) производит дельту. Блок не заменяет вход; он добавляет выученную коррекцию.


Почему это важно

Три причины, почему остаточные соединения доминируют в глубоких архитектурах:


1. Градиентный поток. Во время обратного распространения градиентов добавление дает градиентам прямой путь от выхода обратно ко входу, минуя подслои. Стек из 12 слоев без остатков потерял бы сигнал градиента задолго до достижения эмбеддингов; с остатками величина градиента остается пригодной через сотни слоев.


2. Инициализация идентичностью. При инициализации веса подслоя производят малые выходы. Остаточное соединение означает, что слой N изначально пропускает почти без изменений. Обучение постепенно выучивает дельты, начиная с рабочей отправной точки.


3. Композиционное обучение. Каждый блок выучивает уточнение, а не замену. Слой 1 может добавить позиционную информацию. Слой 2 может добавить синтаксическую структуру. Слой 7 может добавить семантические отношения. Остаточный поток накапливается.


Нормализация слоев

Перед каждым подслоем LayerNorm приводит представление каждого токена к нулевому среднему и единичной дисперсии, затем применяет обучаемые коэффициент усиления и смещение для каждой фичи:


y = gamma * (x - mean(x)) / sqrt(var(x) + epsilon) + beta

Среднее & дисперсия вычисляются по размерности d_model, отдельно для каждого токена. Два обучаемых вектора (gamma, beta, каждый формы [d_model]) восстанавливают выразительный масштаб. Нормализация поддерживает активации в численно стабильном диапазоне; без неё небольшие нестабильности обучения накапливаются в NaN-градиенты.

Pre-Norm против Post-Norm

Тонкий, но критически важный выбор

Два способа подключения layer norm в остаточный подслой:


Post-norm (оригинальная статья 2017 года):

x = LayerNorm(x + Attention(x))

Layer norm находится после остаточного сложения. Сам поток остатка нормализуется на каждом слое.


Pre-norm (современный стандарт, используется в ANDREA):

x = x + Attention(LayerNorm(x))

Layer norm находится перед подслоем, внутри остаточной ветви. Остаточный поток остаётся ненормализованным; нормализуется только вход в подслоем.


Почему победил Pre-Norm

Post-norm обучается плохо без разогрева LR и тщательной настройки гиперпараметров. Градиенты взрываются в ранних слоях, потому что каждый layer norm перемешивает накопленное состояние остаточного потока. Оригинальная статья 2017 года использовала post-norm с обширной настройкой; последующие работы (GPT-2, LLaMA, ANDREA) перешли на pre-norm.


Обучение до нормализации проходит стабильно. Остаточный поток накапливается чисто через все слои; нормализация применяется только к входам подслой для численной стабильности. Современные трансформеры по умолчанию используют pre-norm, & ANDREA наследует этот выбор.


Финальное уравнение блока

Комбинируя остатки, нормализацию слоя в позиции pre-norm & оба подслоя, получаем полный блок ANDREA:


```python
def block_forward(x):
```
x = x + Attention(LayerNorm(x))   # подслой внимания
x = x + MLP(LayerNorm(x))         # подслой MLP
return x

Два подслоя, два остаточных сложения, две нормализации слоёв (примечание: каждый подслой имеет свою нормализацию слоя; ANDREA-120M имеет 24 нормализации слоёв по 12 блокам плюс одна финальная на выходе, итого 25). Повторить 12 раз. Это ствол ANDREA-120M.

Почему Pre-Norm стабилизирует обучение

ANDREA использует pre-norm: `x = x + Attention(LayerNorm(x))`. Сравните с post-norm: `x = LayerNorm(x + Attention(x))`. Приведите одну причину с точки зрения потока градиентов, почему pre-norm обучается стабильнее post-norm в глубоких стеках. Сослаться на остаточный поток в ответе.

Два линейных слоя, одна активация

Три операции

Подслой MLP — это двухслойный персептрон с нелинейной активацией между слоями:


def mlp_forward(x):
h = x · W_1 + b_1        # расширение: d_model → mlp_dim
h = GELU(h)              # нелинейная активация
y = h · W_2 + b_2        # сжатие: mlp_dim → d_model
return y

Три операции. Две линейные, одна нелинейная. Первая линейная расширяет ширину; вторая сжимает обратно.


Коэффициент расширения 4×

Современные трансформеры устанавливают mlp_dim = 4 × d_model. ANDREA-120M:


d_model = 768
mlp_dim = 4 × 768 = 3072
Форма W_1 = [768, 3072]      # ~2.36M параметров
Форма W_2 = [3072, 768]      # ~2.36M параметров
Параметры MLP на блок = 4.72M (игнорируя смещения)

Два MLP расположены между каждой парой подслоёв внимания (по одному на блок). Двенадцать блоков × 4.72M ≈ 56.6M параметров MLP всего в ANDREA-120M, примерно половина всех параметров.


Почему 4×

Соотношение 4× возникло эмпирически. Меньшие соотношения снижают ёмкость модели. Большие соотношения дают убывающую отдачу на потраченный параметр. На протяжении десятилетий поиска архитектур 4× выдержало проверку; оно присутствует в GPT, BERT, T5, LLaMA и ANDREA.


Недавние работы (PaLM, Chinchilla) обнаружили, что механизмы гейтинга (SwiGLU) могут использовать расширение 8/3× с сопоставимой ёмкостью при меньших затратах; ANDREA остаётся с классическим GELU + 4× для простоты.

GELU: Плавная активация

Что вычисляет GELU

GELU (Gaussian Error Linear Unit) — стандартная активация между слоями MLP в современных трансформерах. Её формула:


GELU(x) = x · Φ(x)

Φ(x) — это функция распределения стандартного нормального распределения: вероятность того, что случайная величина со стандартным нормальным распределением окажется меньше или равной x. Вычисляется численно:


Φ(x) ≈ 0.5 × (1 + tanh(sqrt(2/π) × (x + 0.044715 × x³)))

Поведение по регионам

- Для больших положительных x: Φ(x) ≈ 1, поэтому GELU(x) ≈ x. Как ReLU.

- Для больших отрицательных x: Φ(x) ≈ 0, поэтому GELU(x) ≈ 0. Как ReLU.

- Около x = 0: Φ(x) ≈ 0.5, поэтому GELU(0) = 0 точно. Плавный переход через начало координат.


В отличие от ReLU, GELU пропускает некоторые отрицательные входы, взвешенные по Φ(x). Маленький отрицательный вход всё ещё даёт маленький отрицательный выход, просто меньше, чем полный вход.


Почему GELU превосходит ReLU

Эмпирически трансформеры, обученные с GELU, достигают меньших потерь, чем трансформеры, обученные с ReLU, при том же количестве параметров. Плавность около нуля имеет значение: жесткий обрыв ReLU в нуле создает разрывы градиентов; плавная кривая GELU обеспечивает более чистые градиенты для обратного распространения.


Тренировочный движок ANDREA microgpt_cuda.cu поставляется с вручную написанным CUDA-ядром GELU. Ядро использует приведенное выше приближение tanh; современные GPU включают tanh как операцию одного инструкции.

Вычисление параметров MLP

ANDREA-120M имеет `d_model=768`, `mlp_dim=3072` и `n_layer=12`. Вычислите общее количество параметров в матрицах весов MLP (`W_1` и `W_2`) по всем 12 блокам. Игнорируйте смещения. Покажите арифметику. Затем укажите, какую долю от ~120M общего количества параметров ANDREA-120M это составляет (округлите до одного знака после запятой).

Двенадцать блоков составляют ANDREA-120M

От блока к модели

Полный прямой проход ANDREA-120M:


def model_forward(token_ids):
x = token_embed(token_ids) + position_embed(positions)
for block_idx in range(n_layer):       # 12 блоков
x = block_forward(x)               # attention + MLP с остаточными связями
x = LayerNorm(x)                       # финальная нормализация
logits = x · token_embed.T             # общие веса для проекции выхода
return logits

Шесть строк. Основная часть находится внутри block_forward, вызываемой двенадцать раз. Встраивания запускают конвейер; связанное развстраивание (та же матрица, используемая для поиска входа, транспонированная для проекции выхода) завершает его.


Глубина как композиция

Каждый блок считывает остаточный поток, вычисляет дельту и добавляет её обратно. После двенадцати проходов поток содержит накопленные вклады от каждого блока. Внутренне слои склонны специализироваться:


- Ранние слои (1-3): синтаксические паттерны, позиционная структура

- Средние слои (4-8): отношения между словами, границы фраз

- Поздние слои (9-12): семантическое содержание, фактическое вспоминание


Эта специализация возникает из-за тренировочного давления, а не из архитектурных выборов. Один и тот же дизайн однородных блоков производит специализированные слои при обучении на языке.


Общее количество параметров блока


КомпонентНа блокПо 12 блокам
Проекции внимания (4×W)2.36M28.3M
Весы MLP (W_1 + W_2)4.72M56.6M
Нормализация слоев (gamma, beta)~3K (незначительно)~37K
Итого на блок~7.1M~85M

85M параметров в стволе. Добавляем ~13M в эмбеддинги токенов (8449 словарный запас × 768 d_model × 2 для связанных вход/выход) плюс финальную нормализацию слоя, & общее количество параметров ANDREA-120M составляет примерно 120M. Дизайн блока составляет две трети; эмбеддинги — остальное.

Отслеживание одного токена через один блок

768-мерный вектор токена входит в блок 7 ANDREA-120M. Опишите, что с ним происходит внутри блока (в структуре pre-norm). Упомяните: обе нормализации слоев, оба подслоя, оба остаточных сложения & финальную форму. Укажите хотя бы одно место, где поток остатка остается нетронутым & одно место, где он модифицируется.