Глава 6. Нормализация как контракт между слоями
Представьте пайплайн из сотни стадий.
Если формат данных на выходе первой стадии плывёт каждый батч,
остальные девяносто девять всё время переучиваются жить в новом мире.
Residual вернул градиентам дорогу.
Но осталась другая болезнь глубоких систем: нестабильность распределений по дороге вперёд.
Слой №17 учится ожидать входы примерно определённого масштаба.
Слой №3 тем временем обновляет веса — и меняет статистику всего, что течёт дальше по сети.
Для №17 это выглядит как землетрясение под фундаментом.
6.1. Эффект бабочки в весах
В литературе это долго обсуждали под ярлыком Internal Covariate Shift: распределение входов внутренних слоёв меняется во время обучения.
Споры о том, насколько именно этот ярлык объясняет успех BatchNorm, не закрыты.
Для инженера важнее наблюдаемый факт:
Глубокие сети без явной нормализации часто требуют ювелирного LR,
аккуратной инициализации и всё равно капризничают.
С нормализацией обучение обычно становится проще и быстрее.
Механика боли:
батч t: слой 3 выдаёт активации с mean≈0.2, std≈1.1
обновили веса
батч t+1: слой 3 выдаёт mean≈1.4, std≈3.7
слой 10: «я учился под другой режим входа»
Это похоже не на «ошибку формулы», а на отсутствие контракта между модулями системы.
В программной инженерии мы фиксируем API.
В глубокой сети нормализация — один из способов зафиксировать статистический API между слоями.
6.2. Batch Normalization: выравнивание по батчу
Идея BatchNorm проста до наглости.
Для каждой активации (в CNN — обычно по каналу) внутри батча:
- посчитать среднее и дисперсию по батчу;
- вычесть среднее, поделить на корень из дисперсии;
- разрешить сети заново масштабировать и сдвинуть результат обучаемыми
γиβ.
x → normalize(x; μ_B, σ_B) → γ · x̂ + β
Зачем γ и β, если мы только что всё выровняли?
Потому что иногда слою полезен не стандартный масштаб.
Мы даём стабильную стартовую точку и оставляем свободу отойти от неё, если градиенты так решат.
Эффекты, которые обычно видят на практике:
- можно поднять learning rate;
- обучение менее чувствительно к инициализации;
- глубже/быстрее сходятся многие CNN.
Это снова обмен:
| Получили | Чем заплатили |
|---|---|
| Стабильность и скорость обучения | Зависимость от статистики батча |
| Меньше ручной магии с LR | Сложности в inference/online и малых батчах |
| Регуляризующий побочный эффект | Расхождение train (по батчу) vs eval (running stats) |
На инференсе нельзя считать μ/σ по одному картинке так же надёжно, как по батчу.
Поэтому хранят скользящие средние статистики, собранные на train. Ещё один контракт — уже между режимами train и eval.
6.3. Жизнь после батча: когда BatchNorm мешает
BatchNorm прекрасен, пока батч большой и i.i.d.-подобный.
Он начинает скрипеть, когда:
- батч крошечный (мобильное обучение, огромные картинки, multi-GPU с маленьким куском на девайс);
- статистика батча плохая оценка реального распределения;
- задача ближе к NLP/трансформерам, где другая ось нормализации естественнее;
- нужен детерминированный выход, жёстко независимый от соседей по батчу.
Тогда появляются родственники:
BatchNorm — статистика по батчу (и обычно по H×W для CNN-канала)
LayerNorm — статистика по признакам одного сэмпла/токена
GroupNorm — каналы делятся на группы; удобно при малых батчах
InstanceNorm— по сути экстремальный случай на экземпляр/канал
flowchart TD
P[Проблема: плывут распределения между слоями] --> BN[BatchNorm]
BN --> OK[Большие батчи CNN: часто отлично]
BN --> BAD[Малые батчи / чувствительность к соседям]
BAD --> GN[GroupNorm / InstanceNorm]
P --> LN[LayerNorm]
LN --> TR[Трансформеры, NLP, многие ViT-стеки]
Не нужно запоминать это как зоопарк ради зоопарка.
Нужна развилка:
По какой оси мы договорились считать “нормальный” масштаб —
и стабильна ли эта ось в нашем режиме обучения и деплоя?
6.4. Нормализация рядом с residual
На практике residual и нормализация живут вместе.
Типичный современный кусок CNN-блока — не «голые свёртки», а согласованный ритуал: свёртка, нормализация, активация, skip.
Порядок деталей эволюционировал (pre-norm / post-norm в трансформерах — отдельная сага), но принцип один:
короткий путь сигнала + стабильный масштаб активаций
= глубина, которую можно оптимизировать
Без skip градиент тонет.
Без нормализации (или её функциональных заменителей вроде аккуратной инициализации и масштабов) обучение часто превращается в настройку детонатора.
Часть II — два стабилизатора глубины
| Residual | Normalization |
|---|---|
| Путь для сигнала и градиента | Контракт о масштабе данных |
| «Учи разницу» | «Передавай в договорном виде» |
6.5. Закрываем Часть II
Кризис глубины был не про то, что «глубокое = плохо».
Он был про то, что наивный стек преобразований ломает два канала связи:
- канал ошибки назад;
- канал статистики вперёд.
Residual и нормализация — два разных договора, которые вернули глубине смысл.
Дальше книга меняет полигон.
Мы умеем извлекать признаки. Вопрос станет жёстче: как из карты признаков получить много объектов с координатами быстро. Именно здесь появится развилка R-CNN против YOLO — и вся инженерия шеи, голов и функций потерь.
Если бы вы были автором статьи…
-
Сконструируйте провал BatchNorm: задача, железо, размер батча.
Какую альтернативную нормализацию предложите и какой абляцией докажете выигрыш? -
Нужны ли γ и β?
Что произойдёт, если зафиксировать их как 1 и 0? Когда сеть обязана уметь «разнормализовать»? -
Связка с главой 5: нарисуйте блок
Conv → Norm → ReLUсо skip.
Куда вы воткнёте shortcut — до нормы, после, вокруг двух свёрток? Почему?
В Части III мы наконец поставим вопрос детекции так, как его ставит продукт: не «есть ли на фото машина», а «где все объекты, и успеваем ли мы ответить за бюджет latency».