Диагностика Mock-интервью
Главная · Нейронные сети

Практика обучения: батчи, dropout, batchnorm

Формулу градиентного спуска знают все, но сети «не учатся» по десятку прозаичных причин: не тот learning rate, забытый warmup, нулевая инициализация. Эта тема — про инженерную кухню обучения и про то, как ставить диагноз по кривым loss.

Интуиция

Архитектура сети — это рецепт, а обучение — сама выпечка: важны температура (learning rate), время (эпохи) и порядок действий. Приборная панель пекаря — две кривые обучения (learning curves): ошибка на обучающей выборке (train loss) и на отложенной (validation loss). Почти любую проблему видно по их форме — этим мы и займёмся в интерактиве.

Мини-батчи и эпохи

Считать градиент по всему датасету дорого, по одному примеру — слишком шумно. Компромисс — мини-батч (mini-batch): случайная пачка из 32–1024 примеров, по которой оценивается градиент. Полный проход по всем данным называется эпохой (epoch).

Размер батча — это компромисс. Маленький батч даёт шумную оценку градиента: обучение «дрожит», зато шум работает как лёгкая регуляризация и помогает выбираться из плохих мест ландшафта. Большой батч даёт точный градиент и полностью загружает GPU, но ест память, а слишком большой — часто ухудшает обобщение, потому что сходится в «острые» минимумы. На практике берут максимум, который влезает в память, и при удвоении батча пропорционально поднимают learning rate.

Расписание learning rate

Постоянный learning rate — почти всегда не оптимум. Типичное расписание (learning rate schedule):

💡 Ключевая мысль Почти все проблемы обучения диагностируются по двум кривым — train loss и val loss. Научись читать их форму, и половина «сеть не учится» превратится в конкретный список действий.

Dropout: учим ансамбль в одной сети

Dropout — на каждом шаге обучения случайно «выключаем» каждый нейрон слоя с вероятностью p (обычно 0.1–0.5). Сеть не может положиться на конкретный нейрон или на сговор пары нейронов (co-adaptation) — признаки становятся избыточными и устойчивыми. Красивая интерпретация: мы обучаем экспоненциально большой ансамбль подсетей с общими весами.

Критично помнить про режимы: на инференсе dropout выключен — работают все нейроны. Чтобы масштаб активаций совпадал, при обучении оставшиеся активации делят на 1 − p (inverted dropout). В коде это переключатели model.train() / model.eval().

Нормализация активаций

По мере обучения распределения активаций внутри сети «плывут», и каждому слою приходится подстраиваться под меняющийся вход. Нормализация приводит активации к стабильному масштабу (среднее 0, дисперсия 1, плюс обучаемые сдвиг и масштаб) — градиенты становятся здоровее, можно брать больший learning rate, обучение ускоряется.

Инициализация и защита от взрывов

Инициализировать веса нулями — катастрофа: все нейроны слоя получают одинаковые градиенты и навсегда остаются копиями друг друга (симметрия не разрушается) — сеть вырождается в один нейрон. Слишком большие случайные веса — активации насыщаются или взрываются. Правильный масштаб задают схемы Xavier (Glorot, для tanh/sigmoid: дисперсия ≈ 1/n) и He (для ReLU: дисперсия ≈ 2/n), где n — число входов нейрона.

Последний страховочный трос — обрезка градиентов (gradient clipping): если норма градиента превышает порог, градиент масштабируют вниз. Один аномальный батч не сможет «выстрелить» веса в космос; стандартная практика для RNN и LLM.

Диагностика по кривым

⚠️ Подводный камень Dropout и batchnorm ведут себя по-разному при обучении и инференсе. Забытый model.eval() — классический баг: метрики на проде «пляшут», хотя веса те же. И наоборот: включив eval во время обучения, вы молча отключите dropout.
🎤 На собеседовании
  • «Почему нельзя инициализировать веса нулями?» — симметрия: одинаковые нейроны получают одинаковые градиенты и никогда не различатся.
  • «Что делает dropout на инференсе?» — ничего: он выключен, а масштаб компенсирован делением на 1 − p при обучении.
  • «Чем layer norm лучше batch norm для трансформеров?» — не зависит от размера батча и длины последовательности, нет бегущих статистик и различий train/eval.
  • «Loss стал NaN на 50-м шаге — действия?» — уменьшить lr, включить warmup и gradient clipping, проверить данные на выбросы/нули в логарифмах.