Backprop и оптимизация нейросетей
Backprop и оптимизаторы - фундамент, по которому отличают «запускал обучение» от «понимаю, что происходит». Дежурные вопросы: почему Adam, что делает momentum и что крутить, когда лосс улетел в NaN.
// Learning rate - главный гиперпараметр диплёрнинга. Если из урока запомнить одно это.
Backprop: цепное правило по графу
Обучение - две фазы по вычислительному графу: forward считает значения и запоминает промежуточные, backward цепным правилом протаскивает градиент лосса ко всем параметрам за один проход.
В глубоких сетях градиент - произведение многих якобианов: оно легко уходит в ноль (затухание) или в бесконечность (взрыв). Лечат ReLU-семейством вместо насыщающихся сигмоид, нормализацией, skip-связями и клипом градиента.
// Практическая деталь-детектор: в PyTorch градиенты накапливаются - забытый zero_grad перед backward тихо портит обучение.
- gradient clipping
- обрезка нормы градиента - страховка от взрыва
SGD → momentum → Adam → AdamW
SGD (stochastic gradient descent) на мини-батчах: шум батча, и цена, и бесплатный регуляризатор. Momentum накапливает направление движения и гасит осцилляции поперёк оврага лосса.
Adam добавляет адаптивный масштаб шага по каждой координате (оценки первого и второго моментов): быстрый уверенный старт из коробки - дефолт большинства задач. AdamW отделяет weight decay от адаптивного шага - корректная L2 для Adam и стандарт трансформеров.
// Классика собеса: L2 «как в SGD» внутри Adam искривляется адаптивным шагом, поэтому AdamW существует как отдельный оптимизатор.
- momentum
- накопленное направление шага; гасит осцилляции
- weight decay
- усадка весов; в AdamW - отдельно от адаптивного шага
Learning rate и батч
Слишком большой lr - расходимся или скачем вокруг минимума; слишком малый - ползём и застреваем. Планировщики решают конфликт «быстро в начале, аккуратно в конце»: warmup стабилизирует старт, cosine/step decay сбавляют к финалу.
Размер батча связан с lr (больше батч - можно больше lr) и влияет на шум градиента и обобщение. Упёрся в память GPU - gradient accumulation эмулирует крупный батч несколькими мелкими шагами без step.
// Диагноз по кривой лосса: расходится - lr вниз; идёт лесенкой - работает планировщик; дрожит - батч мал.
- warmup
- плавный разгон lr в первые шаги - стабилизация старта
Как отвечать: «Лосс скачет или улетел в NaN - что делать?»
Иду по чек-листу от дешёвого к дорогому. Первое - learning rate вниз в разы и gradient clipping: взрыв градиента - самая частая причина. Второе - данные: NaN и бесконечности во входе, необрезанные выбросы, деление на ноль или лог нуля в кастомном лоссе. Третье - если это mixed precision fp16, проверяю loss scaling: underflow градиентов даёт NaN. И только когда всё это чисто, думаю про архитектуру. «Добавить слоёв» - последний пункт списка, а не первый.
Отладочный маршрут в порядке частоты причин - ровно то, чем занимаешься в реальном обучении, и противоположность карго-культу «крутить архитектуру».
На чём валят
- −Сигмоида/tanh во всех скрытых слоях глубокой сети - насыщение и затухший градиент; дефолт - ReLU-семейство.
- −Забытый zero_grad перед backward в PyTorch - градиенты накапливаются между шагами.
- −Adam с L2 «как в SGD» - регуляризация искривляется адаптивным шагом; поэтому AdamW.
- −Лосс скачет/NaN - сначала lr вниз и clip, а не «добавить слои».
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 14, остальные разбираются в тренажёре.
- Зачем нужен learning rate warmup в начале обучения больших моделей?A)Нужен, чтобы прогреть GPU до рабочей температуры перед обучениемB)Уменьшает потребление видеопамяти в первые шаги обучения моделиC)На старте моменты Adam сырые — плавный рост lr стабилизируетD)Это форма регуляризации, заменяющая dropout в трансформерах
показать ответ и разбор
+C)На старте моменты Adam сырые — плавный рост lr стабилизирует// разбор: На старте оценки моментов Adam смещены, LayerNorm-статистики «сырые», а градиенты в глубоких трансформерах особенно шумные — полный lr сразу часто даёт расходимость. Типовая схема: линейный warmup несколько сотен/тысяч шагов, затем cosine/linear decay. Для больших батчей warmup практически обязателен.
- Почему нельзя инициализировать все веса сети нулями?A)Сеть с нулевой инициализацией обучается слишком быстро и расходитсяB)Нулевые веса вызывают переполнение float при первом же прямом проходеC)Симметрия: нейроны получают равные градиенты и остаются копиямиD)Можно, современные оптимизаторы сами разрывают симметрию весов
показать ответ и разбор
+C)Симметрия: нейроны получают равные градиенты и остаются копиями// разбор: При одинаковых весах выходы и градиенты нейронов идентичны, обновления тоже — симметрию ничто не ломает (кроме dropout-шума, но полагаться на это нельзя). Поэтому веса инициализируют случайно с правильным масштабом: Xavier/Glorot для tanh/сигмоид, He — для ReLU; bias нулями — можно.
- Чем ReLU лучше сигмоиды как активация в скрытых слоях?A)ReLU даёт более высокую точность на большинстве задачB)ReLU нормирует выход слоя строго в диапазон от нуля до единицыC)ReLU не насыщается на положительных входах — градиент не гаснет, и дешевлеD)ReLU устраняет необходимость в инициализации весов сети
показать ответ и разбор
+C)ReLU не насыщается на положительных входах — градиент не гаснет, и дешевле// разбор: Сигмоида насыщается на больших по модулю входах — её производная стремится к нулю, и градиент затухает по глубине. ReLU = max(0, x) линейна при x>0, поэтому градиент не гаснет, а сама операция дешевле экспоненты. Расплата — «мёртвые» нейроны при x<0, что смягчает Leaky ReLU/GELU.
- Чем mini-batch градиентный спуск отличается от full-batch и чистого SGD?A)Метод mini-batch считает градиент по одному примеру за шагB)Mini-batch — компромисс: градиент по порции, стабильнее SGD и дешевле full-batchC)Full-batch и mini-batch — это два названия одного и того же методаD)Стохастический спуск обязательно использует сразу весь датасет на каждом шаге
показать ответ и разбор
+B)Mini-batch — компромисс: градиент по порции, стабильнее SGD и дешевле full-batch// разбор: Full-batch считает точный градиент по всем данным (дорого и не влезает в память), чистый SGD — по одному примеру (очень шумно). Mini-batch берёт порцию (32–512): градиент менее шумный, чем у SGD, вычисления влезают в память GPU и хорошо параллелятся. Это дефолт обучения нейросетей.
- Лосс в глубокой рекуррентной сети внезапно взлетает до огромных значений. Какой механизм и стандартное лечение?A)Взрывающиеся градиенты: норма градиента растёт лавинообразно и рвёт шаг; стандартно лечат клиппингом градиента по нормеB)Это затухающие градиенты, и решение — увеличить скорость обучения в десятки раз, чтобы они перестали затухатьC)Сеть просто переобучилась на трейне, и достаточно добавить в неё ещё больше слоёв, чтобы значения лосса сами пришли в нормуD)Это нормальное штатное поведение рекуррентной сети, и вмешиваться в процесс обучения здесь не требуется
показать ответ и разбор
+A)Взрывающиеся градиенты: норма градиента растёт лавинообразно и рвёт шаг; стандартно лечат клиппингом градиента по норме// разбор: Резкий скачок лосса до огромных значений или NaN — признак взрывающихся градиентов: в глубоких и рекуррентных сетях произведение множителей по цепочке разрастается, шаг оптимизатора улетает, веса портятся. Стандартное лекарство — gradient clipping по норме (обрезать общую норму градиента порогом), плюс аккуратный learning rate и нормализации. Это противоположность затуханию градиентов и не переобучение.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.