Эпоха 4 · Архитектуры и масштаб · 2015

26 Batch Normalization

Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift · Ioffe & Szegedy · ICML
🟧 оригинал выборочно~45 миноригинал ↗
Суть за 20 секунд. Нормируем вход каждого слоя по мини-батчу (нулевое среднее, единичная дисперсия) + обучаемые масштаб и сдвиг. Активации стабилизируются → больше learning rate, быстрее сходимость, меньше зависимость от инициализации. Почти обязательный компонент CNN.

Контекст

Глубокие сети чувствительны к инициализации и learning rate; распределение входов каждого слоя «плывёт» по мере обучения предыдущих, замедляя сходимость. Иоффе и Сегеди дают на это лекарство.

Идея и механизм

Для каждого мини-батча нормируем вход слоя по каждому признаку, затем масштабируем и сдвигаем обучаемыми γ, β (чтобы сеть при желании вернула любое распределение). На инференсе вместо статистик батча используем бегущие средние, накопленные при обучении.

оптимизация Преобразование BN и спор о том, почему оно работает

Для мини-батча B по каждому признаку считаем среднее и дисперсию, нормируем и применяем обучаемые параметры:

μB = mean(x),   σ²B = var(x)
x̂ = x − μB√(σ²B + ε),   y = γ x̂ + β

Обучаемые γ, β важны: без них слой не смог бы при необходимости восстановить полезное распределение — нормировка не должна обеднять представление.

Спор о причине. Авторы объясняли эффект уменьшением «internal covariate shift» (дрейфа распределений между слоями). Позже MIT-работа (2018) это оспорила: измерения показали, что BN не столько убирает дрейф, сколько сглаживает ландшафт потерь (делает градиенты предсказуемее), отчего и можно брать больший шаг. Так что цитируйте BN как технику-веху, но осторожно с её исходным объяснением.

NumPy Forward Batch Normalization
import numpy as np

def batchnorm(x, gamma, beta, eps=1e-5):   # x: (batch, features)
    mu  = x.mean(0)
    var = x.var(0)
    xhat = (x - mu) / np.sqrt(var + eps)    # нормировка по батчу
    return gamma * xhat + beta              # обучаемые масштаб/сдвиг
# на инференсе mu, var берут как бегущие средние с обучения
батч активаций − μ, ÷ σ центр 0, дисперсия 1 γ·x̂ + β стабильные активации
Активации батча центрируются и масштабируются к стандартному виду, затем обучаемые γ, β возвращают нужную форму. Распределения перестают «плыть».
Аналогия. Преподаватель, который перед каждым заданием приводит оценки группы к единой шкале (среднее 0, разброс 1). Тогда следующий «слой» проверяющих всегда работает с предсказуемым масштабом и не сбивается, когда предыдущие стали ставить систематически выше или ниже. γ и β — это право вернуть свою шкалу, если она и правда нужна.

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

Стало почти обязательным в CNN; ускорило обучение глубоких сетей в разы (та же точность за ~14× меньше шагов) и снизило зависимость от инициализации. В трансформерах чаще LayerNorm (нормировка по признакам одного примера, не по батчу) — но идея «нормируй активации» оттуда же.

Связи

→ включён в27. ResNet

ResNet ставит BatchNorm в каждый остаточный блок. Вместе skip-связи и BN — две опоры, на которых стоят очень глубокие сети: одна спасает градиент, другая стабилизирует активации.

↔ соперник19. Dropout

Оба регуляризуют/стабилизируют, но по-разному, и плохо уживаются: BN полагается на статистику батча, а dropout её зашумляет. С приходом BN и больших данных dropout в свёрточных сетях заметно потеснили.

↔ заменён в32. Transformer

Трансформеры используют не BatchNorm, а LayerNorm — нормировку по признакам одного примера. Причина: в NLP батчи разной длины и зависимость от статистики батча вредна; нормировка «внутри примера» устойчивее.

Вопросы пытливого ума

Если объяснение через «covariate shift» неверно, почему BN всё равно так помогает?

Потому что польза реальна, а вот её механизм оказался другим. По данным MIT-работы, BN делает ландшафт потерь глаже — градиенты становятся стабильнее и предсказуемее, что и позволяет больший learning rate и быструю сходимость. Эффект тот же, причина — не та, что заявляли авторы. Классический случай «работает, но не по той теории».

Почему BN плохо работает при маленьком размере батча?

Статистики μ и σ оцениваются по батчу; на батче из 2–4 примеров они шумные и нестабильные, и нормировка начинает вредить. Для таких случаев придумали альтернативы, не зависящие от батча: LayerNorm, GroupNorm, InstanceNorm. Зависимость от размера батча — главная практическая слабость BatchNorm.

BN ведёт себя по-разному на обучении и инференсе — это не источник багов?

Ещё какой. На обучении используются статистики текущего батча, на инференсе — накопленные бегущие средние. Забыть переключить модель в eval-режим — классическая ошибка, дающая «плавающие» предсказания. И если распределение на инференсе отличается от обучающего, бегущие средние могут не подойти. Двойной режим BN — известный источник тонких багов.

Что читать в оригинале

Конспекта + ключевых мест достаточно: само преобразование и режимы train/inference. Про «почему работает» полезнее прочитать критику (MIT 2018), чем исходное объяснение.