Глава 4. Проблема глухого телефона
Исследователи столкнулись со странной ситуацией.
Чем больше слоёв они добавляли, тем хуже становилась сеть.
Это противоречило инженерной интуиции.
В обычном софте «добавить модуль» редко делает систему слабее по выразительности.
В глубоких сетях начала 2010-х именно это и происходило: 56 слоёв проигрывали 20 на той же задаче — и это был не классический overfitting.
Часть I дала нам хороший кирпич: свёртку.
Часть II начинается с вопроса, почему из этих кирпичей нельзя просто сложить высокую башню.
4.1. Цепное правило и его пределы
Обучение сети — это правка весов по градиенту ошибки.
Ошибка считается в конце.
Веса живут по всей глубине.
Значит, сигнал «ты виноват вот на столько» должен пройти назад через все слои.
Математически это цепное правило: производная сложной функции есть произведение локальных производных.
Инженерно это выглядит так:
Если типичный множитель по модулю меньше единицы, произведение из десятков таких множителей стремится к нулю.
Если больше единицы — взрывается.
|0.9| ⁵⁰ ≈ 0.005 → сигнал почти умер
|1.1| ⁵⁰ ≈ 117 → сигнал разнёсся
Это и есть каркас проблем vanishing и exploding gradients.
Не «сеть глупая». А «почта с градиентами не доходит» или «доходит письмом, написанным взрывом».
Аналогия ближе к инженерии, чем к поэзии:
Вы отлаживаете пайплайн из 50 стадий.
На выходе метрика плохая.
Вы хотите понять, какая ранняя стадия виновата.
Но каждый лог по дороге умножает сигнал на 0.9 —
к первой стадии доходит шум уровня округления.
4.2. Экспериментальный тупик: это не overfitting
Важный момент, который легко пропустить.
Если бы глубокая сеть просто запоминала train и проваливала val — мы сказали бы: переобучение, регуляризация, данные.
Но в классических экспериментах того периода (в духе того, что позже аккуратно разложит ResNet-статья) картина была злее:
Глубокая сеть хуже уже на обучении.
Она не «слишком гибкая». Она не может нормально оптимизироваться.
Это меняет диагноз:
| Симптом | Типичный вывод | Здесь |
|---|---|---|
| Val падает, train отличный | Overfitting | Не главный сюжет |
| Train и val оба плохие у более глубокой | Недообучение / плохая оптимизация | Да |
| Добавили слоёв — стало хуже | «Нужно ещё данных» | Недостаточно |
Пока диагноз неверный, лечение тоже будет неверным: dropout и больше картинок не чинят мёртвый обратный проход.
4.3. Вычислительная деградация сигнала
Градиент — не единственная жертва глубины.
Вперёд тоже происходит порча.
Каждый слой — нелинейное преобразование.
После десятков преобразований представление может:
- схлопнуться в узкий динамический диапазон;
- потерять различия, которые ещё были на средних слоях;
- стать численно неудобным для следующих матриц/свёрток.
Отсюда образ глухого телефона:
Слой 1 услышал фразу нормально
Слой 8 уже «что-то про кошку»
Слой 20 «животное?»
Слой 50 шум / одно и то же пятно признаков
Даже если бы градиенты как-то доходили, ранняя часть сети должна уметь менять представление так, чтобы поздней части стало легче.
Если ранние слои почти не получают сигнала об ошибке, они замирают в полуслучайной инициализации. Поздние слои вынуждены героически классифицировать мусор.
flowchart TD
A[Глубокий стек Conv] --> B[Прямой путь: сигнал размывается]
A --> C[Обратный путь: градиент затухает/взрывается]
B --> D[Поздние слои видят бедное представление]
C --> E[Ранние слои почти не учатся]
D --> F[Train error не падает]
E --> F
F --> G[Вывод: проблема оптимизации и прохождения сигнала]
4.4. Что пробовали до «правильного» ответа
Полезно не прыгать сразу к residual. Иначе создаётся иллюзия, что решение было очевидно.
Гипотеза 1. Лучшая инициализация.
Аккуратно выбрать стартовый масштаб весов (Xavier/Glorot, позже He), чтобы дисперсия активаций не умирала на первых же слоях. Помогло. Не отменило кризис на очень большой глубине.
Гипотеза 2. Другие активации.
Сигмоида насыщается → локальная производная около нуля → vanishing ускоряется. ReLU снимает часть боли в положительной полуоси. Снова: лучше, но не «ставь 1000 слоёв и спи спокойно».
Гипотеза 3. Нормализация / аккуратный learning rate.
Позже BatchNorm станет отдельной главой. Он стабилизирует распределения, но сам по себе не объясняет весь сюжет «глубокая хуже мелкой на train».
Гипотеза 4. Просто не делать так глубоко.
Рабочий инженерный ответ на годы. VGG уже глубокая по меркам времени, но потолок всё равно ощущался.
Ни одна из гипотез не отменяет странный факт:
Если более глубокая модель содержит мелкую как частный случай
(достаточно уметь вести себя как тождественное отображение в лишних слоях),
то почему она не может хотя бы не проиграть мелкой?
Этот вопрос — мост к следующей главе.
4.5. Переформулировка проблемы
К концу главы полезно сменить формулировку.
Плохая формулировка:
«Глубокие сети плохие.»
Рабочая формулировка:
«Наш способ складывать слои не даёт оптимизатору лёгкого пути
реализовать тождественное преобразование.
Лишняя глубина становится не ресурсом, а препятствием.»
Что сломалось
- Градиент не доезжает до ранних слоёв.
- Прямой сигнал деградирует по дороге.
- Лишние слои не умеют «просто ничего не менять».
- Поэтому глубина ≠ автоматическая мощность.
Как только проблема звучит так, решение перестаёт быть «ещё один хитрый нелинейный блок».
Решение должно вернуть сети лёгкий режим: «если новый слой не нужен — будь прозрачным».
Если бы вы были автором статьи…
-
Как экспериментально отличить vanishing gradients от обычного underfitting?
Какие графики/зонды вы повесите на ранние и поздние слои? -
Если лишние слои теоретически могут реализовать identity, почему оптимизатор сам туда не попадает?
В чём разница между «существует решение» и «его легко найти градиентным спуском»? -
Предложите архитектурный костыль минимальной силы, который улучшает прохождение сигнала назад без смены функции потерь и датасета.
Не обязательно угадывать исторический ответ — важна логика обмена.
В следующей главе исследователи перестанут требовать от каждого слоя учить преобразование «с нуля» и разрешат ему учить только добавку к уже существующему сигналу. Идея окажется подозрительно простой — и подозрительно сильной.