Оптимизация

Нормализация как предобусловливание

BatchNorm, LayerNorm, RMSNorm — одна арифметика, разные оси, и зачем это оптимизации

Шаг 70 из 117 · ~30 мин

Одна арифметика, разные оси

Все нормализующие слои делают одно и то же:

x^=xμσ2+ε,y=γx^+β\hat{x} = \frac{\htmlData{k=centre}{x - \mu}}{\htmlData{k=scale}{\sqrt{\sigma^2 + \varepsilon}}}, \qquad y = \htmlData{k=affine}{\gamma \hat{x} + \beta}

Различаются они только тем, по каким осям берутся μ\mu и σ\sigma. Записанные формулами, они выглядят почти одинаково и потому не запоминаются; нарисованные как разбиение решётки — различаются сразу.

нормированные значения

batch ↓
признаки →
1.002.003.0010.00
2.004.001.008.00
3.001.005.0012.00
0.003.002.009.00
усреднение по
групп
16
Исходные значения. Обратите внимание на последний столбец: там числа около 10, тогда как в остальных — около 2. Это и есть плохо обусловленный вход.

Переключите на RMSNorm и посмотрите на цифры внимательно: среднеквадратичное по строке равно единице, а среднее — нет (около 0.750.75 на этих данных). Это и есть вся разница между LayerNorm и RMSNorm, и именно поэтому RMSNorm дешевле: не нужно считать среднее и не нужно протаскивать его через обратный проход.

Почему это относится к оптимизации

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

Простейший случай — стандартизация входов из урока 050. Признаки с масштабами 11 и 10410^4 дают κ108\kappa \approx 10^8; после нормировки κ\kappa падает до десятков. Нормализующие слои делают то же самое, но внутри сети, где вручную не достать: активации середины сети никто не стандартизует заранее, а их масштабы разъезжаются по ходу обучения.

Три конкретных механизма:

  • выравнивание масштабов активаций → выравнивание кривизны по параметрам → меньшее κ\kappa;
  • сглаживание ландшафта. Работа Santurkar и др. измерила это прямо: с BatchNorm ландшафт лосса вдоль направления шага заметно менее «изломан», то есть эффективная LL меньше и допустимый шаг больше;
  • инвариантность к масштабу весов. Умножьте веса слоя перед нормировкой на cc — выход не изменится вовсе, потому что нормировка поделит на то же cc. Значит, направление весов важно, а их длина — нет.

Третий пункт имеет неожиданное следствие. Раз масштаб весов не влияет на выход, а weight decay всё равно уменьшает норму, то decay в нормализованной сети работает не как регуляризатор в обычном смысле: он управляет эффективным learning rate. Норма весов уменьшается → градиент относительно нормы растёт → эффективный шаг растёт. Это одна из причин, по которой weight decay и learning rate в таких сетях не независимы.

Historical note: не covariate shift

Изначальное объяснение BatchNorm — «уменьшает internal covariate shift» — не подтвердилось. Santurkar и др. показали это экспериментом: если после BatchNorm специально добавить шум, восстановив сдвиг распределений, обучение всё равно остаётся быстрым. Значит, дело не в сдвиге.

Стоит держать это в голове как пример: приём работает, а объяснение, с которым он был предложен, оказалось неверным. Работающая практика — не доказательство теории, стоящей за ней.

Что выбирают и почему

слойусреднение позависит от батчагде применяют
BatchNormоси batchдасвёрточные сети, большие батчи
LayerNormпризнакамнеттрансформеры
RMSNormпризнакам, без центрированиянетсовременные LLM
GroupNormгруппе признаковнетдетекция, малые батчи

Столбец «зависит от батча» — решающий. BatchNorm вносит связь между примерами: результат для одного зависит от того, кто ещё попал в батч. Отсюда все его практические сложности:

  • на инференсе батча нет, приходится хранить running statistics — и режимы обучения и вывода становятся разными, что регулярно даёт баги (забытый model.eval());
  • при малом батче оценки μ\mu и σ\sigma шумны, и качество падает;
  • в рекуррентных сетях и при переменной длине последовательности осмысленной оси batch просто нет.

LayerNorm ничего этого не имеет, потому что считает статистику внутри одного примера. Именно поэтому трансформеры используют его, а не BatchNorm, — и это выбор про воспроизводимость и независимость примеров, а не про качество нормировки.

Pre-norm против post-norm

Последняя деталь, важная для глубоких сетей. Нормировку можно поставить до блока или после:

x+Attn(LN(x))pre-normпротивLN(x+Attn(x))post-norm\underbrace{x + \text{Attn}(\text{LN}(x))}_{\text{pre-norm}} \qquad\text{против}\qquad \underbrace{\text{LN}(x + \text{Attn}(x))}_{\text{post-norm}}

У pre-norm остаётся чистый residual-путь от входа к выходу, по которому градиент проходит без прохода через нормировку. Это делает глубокие стеки обучаемыми без warmup и с меньшей аккуратностью в подборе шага. Post-norm даёт немного лучшее качество при удачной настройке, но заметно капризнее на большой глубине — поэтому современные модели почти все pre-norm.

Источники

Проверки

0 из 2
  1. По какой оси и зачем

    Отметьте все верные утверждения о нормализующих слоях.

  2. LayerNorm против RMSNorm

    Реализуйте normalise_row(values, centre) — нормировку одной строки признаков. Верните [mean_out, rms_out, first, last]:

    • если centre равно 1, это LayerNorm: вычтите среднее и поделите на σ2+ε\sqrt{\sigma^2 + \varepsilon}, где σ2\sigma^2 — дисперсия с делителем nn;
    • если centre равно 0, это RMSNorm: поделите на 1nixi2+ε\sqrt{\frac{1}{n}\sum_i x_i^2 + \varepsilon}, не вычитая среднее;
    • ε=108\varepsilon = 10^{-8};
    • mean_out, rms_out — среднее и среднеквадратичное результата;
    • first, last — первый и последний нормированные элементы.

    Проверки, которые обязаны выполняться: у LayerNorm mean_out равно нулю, а rms_out — единице; у RMSNorm единице равно только rms_out.

    функция normalise_row

    Загрузка редактора…

    Ctrl/⌘ + Enter