Затухающие и взрывающиеся градиенты
Урок объясняет, почему глубокие сети трудно обучать и как градиент теряется или разрастается по пути назад.
Затухание градиента — это экспоненциальное уменьшение сигнала ошибки по мере его прохода через множество слоёв назад; взрыв — обратная беда, когда он неограниченно растёт.
Откуда берётся проблема
Backprop перемножает локальные производные слоёв. Если на каждом слое множитель меньше единицы, их произведение по многим слоям стремится к нулю — до нижних слоёв «доезжает» почти нулевой градиент, и они почти не учатся. Если множители больше единицы — произведение взрывается, веса скачут, обучение разваливается.
Почему виновата sigmoid
Производная sigmoid не превышает 0.25 (максимум в нуле). Перемножим этот максимум по числу слоёв и посмотрим, что остаётся от градиента.
max_deriv = 0.25 # максимум производной sigmoid
grad_signal = 1.0
for layer in range(1, 11):
grad_signal *= max_deriv
if layer in (1, 3, 5, 10):
print(f"После {layer:>2} слоёв градиент <= {grad_signal:.10f}")
Вывод:
После 1 слоёв градиент <= 0.2500000000 После 3 слоёв градиент <= 0.0156250000 После 5 слоёв градиент <= 0.0009765625 После 10 слоёв градиент <= 0.0000009537
После десяти слоёв градиент не превышает 0.0000009 — фактически ноль. Нижние слои такой сети почти не получают сигнала и не обучаются. Именно поэтому до середины 2010-х глубокие сети на sigmoid обучались крайне плохо.
Взрыв градиента
Зеркальная беда: если множители стабильно больше единицы (например, большие веса), произведение растёт экспоненциально. Градиент становится огромным, шаг спуска перелетает, и веса уходят в бесконечность (в коде это всплывает как nan). Особенно характерно для глубоких и рекуррентных сетей.
Как с этим борются
| Приём | Против чего |
| ReLU вместо sigmoid | затухание (производная 1, не сжимает) |
| грамотная инициализация (Xavier, He) | и затухание, и взрыв |
| batch normalization | стабилизирует распределения активаций |
| остаточные связи (residual, как в ResNet) | дают градиенту «короткий путь» в обход слоёв |
| обрезка градиента (gradient clipping) | взрыв (ограничивает норму градиента) |
Все эти приёмы из следующего раздела и из архитектур существуют во многом ради одной цели — чтобы градиент доезжал до глубоких слоёв в целости.
Историческая ремарка
Затухание градиента — не теоретическая тонкость, а реальный барьер, который десятилетиями сдерживал глубокое обучение. В 1990-х сети глубже двух-трёх слоёв на sigmoid почти не обучались: нижние слои не получали сигнала. Перелом случился около 2010–2015 годов, когда сошлись несколько факторов: переход на ReLU, грамотная инициализация (He), batch normalization и остаточные связи. Именно они позволили обучать сети из десятков и сотен слоёв — так появились глубокие CNN вроде ResNet (152 слоя) и, позже, огромные трансформеры. Иными словами, современный бум ИИ во многом стоит на решении проблемы из этого урока.
Запомните диагностический приём: если при обучении потеря почти не двигается, а веса нижних слоёв едва меняются — подозревайте затухание; если же потеря внезапно становится nan или скачет до огромных значений — это взрыв градиента, и помогает clipping или меньший lr.
Итог
- Backprop перемножает производные слоёв; их произведение может затухать или взрываться.
- Sigmoid (производная ≤ 0.25) провоцирует затухание в глубоких сетях.
- ReLU, грамотная инициализация, batch norm, residual-связи и clipping решают проблему.