Модуль 8. Полносвязные сети и backprop¶
После этого модуля вы сможете
- Объяснить, почему без нелинейности между слоями сеть остаётся линейной моделью.
- Вывести формулы обратного прохода для полносвязного слоя, а не списать их.
- Написать сеть с нуля на NumPy и принять её gradient check из модуля 4.
- Показать на числах, почему нулевая инициализация не работает, а слишком большая ломает обучение.
- Честно сравнить сеть с бустингом из модуля 6 и принять результат, каким бы он ни был.
Время: около двух недель. Пререквизиты: модуль 7.
Ноутбук: notebooks/08-neural-networks-and-backprop.ipynb
Зачем это¶
Часть I дала инструменты, часть II — модели и процедуру честного сравнения. Часть III начинает то, ради чего половина людей приходит в машинное обучение.
Начинается она с разочарования, и это полезно. Нейросеть — не новый принцип. Это композиция линейных преобразований из модуля 3 и градиентного спуска из модуля 4, склеенных цепным правилом оттуда же. Ничего, кроме этого, в ней нет.
Весь модуль пишется на NumPy руками. PyTorch появится в следующем, когда станет ясно, что именно он избавляет вас делать.
Почему одного слоя мало¶
Линейная модель проводит гиперплоскость. Данные, которые ей не разделить, строятся за минуту: четыре точки XOR, где класс определяется несовпадением двух признаков.
Гиперплоскости, разделяющей их, не существует. Не «трудно найти» — не существует.
Естественная мысль: поставить два линейных слоя подряд. Не поможет.
Композиция линейных преобразований — линейное преобразование. Из модуля 3: произведение матриц есть матрица. Сто слоёв подряд дают ровно то же, что один.
Между слоями обязана стоять нелинейность. Не для красоты и не «чтобы лучше училось» — без неё глубины просто не существует.
Функции активации¶
| Формула | Производная | Беда | |
|---|---|---|---|
| Сигмоида | \(\sigma(z) = \frac{1}{1+e^{-z}}\) | \(\sigma(1-\sigma)\) | максимум 0.25, градиент затухает |
| Гиперболический тангенс | \(\tanh z\) | \(1 - \tanh^2 z\) | максимум 1, но насыщается на краях |
| ReLU | \(\max(0, z)\) | 0 или 1 | при \(z<0\) нейрон может умереть навсегда |
Про сигмоиду главное — её производная нигде не превышает 0.25. Цепное правило перемножает производные по слоям, и в сети из десяти сигмоидных слоёв градиент у первого слоя умножается на \(0.25^{10} \approx 10^{-6}\). Первые слои перестают учиться.
Это затухание градиента, и оно держало глубокие сети мёртвыми до конца двухтысячных.
ReLU лечит это тем, что её производная равна ровно единице на всей положительной половине. Умножение единиц ничего не затухает. Плата — если нейрон ушёл в отрицательную область на всех примерах, его градиент ноль навсегда, и он мёртв.
Прямой проход¶
Сеть из \(L\) слоёв. Для слоя \(l\):
где \(a^{(0)} = x\) — вход, \(f\) — активация, а на последнем слое активации обычно нет: там сигмоида для двух классов, softmax для многих, ничего для регрессии.
Всё. Прямой проход — это цикл из двух строк.
Обратный проход¶
Теперь главное в модуле.
Нужны \(\partial L/\partial W^{(l)}\) для каждого слоя. Идём цепным правилом справа налево.
Введём \(\delta^{(l)} = \partial L / \partial z^{(l)}\) — насколько потеря чувствительна к входу активации слоя \(l\). Через эту величину всё выражается коротко.
Последний слой. Для пары «сигмоида плюс log loss» из модуля 5 всё сокращается:
Та же формула \((p - y)\), что была там. Сокращение не случайно: функцию потерь и последнюю активацию подбирают в пару именно ради него.
Шаг назад через слой. Зная \(\delta^{(l)}\), получаем предыдущую:
Читается по частям. \(W^{\mathsf{T}}\delta\) — ошибка, разложенная обратно по нейронам предыдущего слоя пропорционально весам, которыми они на неё повлияли. \(\odot f'\) — поэлементное домножение на производную активации: нейрон в насыщении почти не влияет, значит и виноват почти не он.
Градиенты параметров.
Первая формула — та же структура «ошибка умножить на вход», что была у логистической регрессии в модуле 4. Она не изменилась, просто теперь применяется к каждому слою.
Что такое backprop на самом деле
Обратное распространение — это не алгоритм обучения. Это способ посчитать градиент за один проход вместо \(N\) проходов, где \(N\) — число параметров.
Обучает по-прежнему градиентный спуск из модуля 4. Backprop только доставляет ему градиент, и его единственная заслуга — эффективность: он переиспользует уже посчитанные \(\delta\) вместо того, чтобы считать производную по каждому весу заново.
Наивный численный градиент для сети с миллионом параметров потребовал бы два миллиона прямых проходов на каждый шаг. Backprop обходится одним прямым и одним обратным.
Инициализация¶
Вопрос, который выглядит техническим и решает, будет ли сеть учиться вообще.
Нулями нельзя. Если все веса слоя равны, все его нейроны получают одинаковый вход, дают одинаковый выход и получают одинаковый градиент. Они остаются одинаковыми навсегда. Слой из ста нейронов работает как один. Это называется проблемой симметрии, и ломается она только случайностью.
С нулями конкретно всё ещё резче. Градиент первого слоя идёт назад через веса второго — формула \(W^{\mathsf{T}}\delta\) выше, — а они нулевые. Значит он тождественно ноль, и первый слой не двигается вообще, ни на шаг. В ноутбуке это видно: после трёхсот шагов все его веса по-прежнему ровно нули.
Слишком большими нельзя. Активации растут от слоя к слою, сигмоида уходит в насыщение, её производная падает почти до нуля — обучение стоит.
Слишком маленькими нельзя. Сигнал затухает по глубине и до последних слоёв доходит шум.
Рабочее правило — держать дисперсию сигнала постоянной по слоям. Отсюда два стандарта:
Xavier для симметричных активаций (tanh), He для ReLU — двойка компенсирует то, что ReLU обнуляет половину значений.
Gradient check¶
Модуль 4 дал приём, а модуль 8 — задачу, ради которой он нужен.
Формулы обратного прохода выводятся вручную, и ошибиться в них легко: перепутанное транспонирование, потерянный множитель, неправильная ось суммирования. Ошибка не приводит к падению — сеть просто учится хуже, чем могла бы, и понять это невозможно.
Правило: написали слой — проверьте его gradient check, прежде чем обучать. Относительное расхождение меньше \(10^{-7}\) означает, что формула верна. Больше \(10^{-4}\) означает ошибку.
На это уходит минута. На поиск той же ошибки без gradient check уходит день.
Сеть против бустинга¶
Последний раздел модуля, и он проверка на честность.
В модуле 6 бустинг обыграл линейную модель на табличных данных вдвое. Теперь у нас есть сеть. Победит ли она бустинг?
Ставим эксперимент по правилам модуля 7: одни данные, одинаковый бюджет настройки, пять разбиений, доверительные интервалы по бутстрэпу из модуля 1.
Спойлер, потому что прятать результат — это ровно то, против чего написан весь курс: на табличных данных сеть бустинг не обыгрывает. Причины разобраны в модуле 6, и они структурные.
Полезный вывод не в том, что сети плохие. Он в том, что умение обучить сеть не означает, что её надо обучать. В частях IX–XI появятся задачи, где сеть выигрывает с разгромным счётом: изображения, последовательности, текст. Там есть структура, из которой она извлекает пользу. В таблице её нет.
Практика¶
Часть 1. Ноутбук¶
Откройте notebooks/08-neural-networks-and-backprop.ipynb.
Что внутри:
- XOR: линейная модель не может, сеть с одним скрытым слоем может. Видно границу решения.
- Слой как объект: прямой проход в три строки.
- Обратный проход и его gradient check. Затем — намеренно испорченная формула, чтобы увидеть, как проверка её ловит.
- Инициализация: нулями, слишком большая, He. Три кривых обучения.
- Затухание градиента по глубине: сигмоида против ReLU, градиент первого слоя в числах.
- Сеть против бустинга на табличных данных модуля 6, с интервалами.
Часть 2. Своя сеть¶
- Добавьте в код ноутбука ещё одну активацию — tanh или Leaky ReLU.
- Проверьте её gradient check. Пока не сошлось — не обучайте.
- Постройте кривые обучения для трёх активаций на одних данных и зёрнах.
- Найдите глубину, на которой сигмоидная сеть перестаёт учиться совсем. Посчитайте градиент первого слоя и сравните с \(0.25^{\text{глубина}}\).
Задание¶
- Выведите на бумаге \(\delta^{(l-1)}\) через \(\delta^{(l)}\). Не подглядывая в текст.
- Докажите, что два линейных слоя без активации эквивалентны одному. Двух строк достаточно.
- Реализуйте softmax и кросс-энтропию для нескольких классов. Покажите, что \(\delta^{(L)}\) снова равна \(a - y\).
- Инициализируйте сеть нулями и покажите численно, что все нейроны скрытого слоя остаются одинаковыми после ста шагов.
- Возьмите свою табличную задачу из модуля 6 и повторите сравнение с бустингом честно. Запишите вывод в формате модуля 1: величина, условия, база.
Пятый пункт — тот же, что был в модуле 6, и это намеренно. Теперь у вас на одну модель больше, а правила сравнения не изменились.
Проверка себя¶
- Почему без нелинейности глубина не даёт ничего?
- Чему равен максимум производной сигмоиды и что из этого следует для глубоких сетей?
- Что такое \(\delta^{(l)}\) на словах?
- Объясните \(W^{\mathsf{T}}\delta\) и поэлементное умножение на \(f'\) по отдельности.
- Backprop — это алгоритм обучения? Если нет, то что?
- Почему нельзя инициализировать веса нулями?
- Откуда в инициализации He двойка?
- Сеть проиграла бустингу на таблице. Какой из этого вывод, а какой — нет?
Дальше¶
В модуле 9 появляются свёртки — первая архитектура, которая использует структуру данных, а не просто перемалывает признаки. Там же сеть впервые выиграет у бустинга, и выиграет с большим отрывом.
Нейросеть — это композиция линейных слоёв, склеенная цепным правилом. Умение её обучить не означает, что её надо обучать.