Перейти к содержанию

Модуль 8. Полносвязные сети и backprop

После этого модуля вы сможете

  • Объяснить, почему без нелинейности между слоями сеть остаётся линейной моделью.
  • Вывести формулы обратного прохода для полносвязного слоя, а не списать их.
  • Написать сеть с нуля на NumPy и принять её gradient check из модуля 4.
  • Показать на числах, почему нулевая инициализация не работает, а слишком большая ломает обучение.
  • Честно сравнить сеть с бустингом из модуля 6 и принять результат, каким бы он ни был.

Время: около двух недель. Пререквизиты: модуль 7. Ноутбук: notebooks/08-neural-networks-and-backprop.ipynb

Зачем это

Часть I дала инструменты, часть II — модели и процедуру честного сравнения. Часть III начинает то, ради чего половина людей приходит в машинное обучение.

Начинается она с разочарования, и это полезно. Нейросеть — не новый принцип. Это композиция линейных преобразований из модуля 3 и градиентного спуска из модуля 4, склеенных цепным правилом оттуда же. Ничего, кроме этого, в ней нет.

Весь модуль пишется на NumPy руками. PyTorch появится в следующем, когда станет ясно, что именно он избавляет вас делать.

Почему одного слоя мало

Линейная модель проводит гиперплоскость. Данные, которые ей не разделить, строятся за минуту: четыре точки XOR, где класс определяется несовпадением двух признаков.

Гиперплоскости, разделяющей их, не существует. Не «трудно найти» — не существует.

Естественная мысль: поставить два линейных слоя подряд. Не поможет.

\[W_2(W_1 x) = (W_2 W_1)\,x = W x\]

Композиция линейных преобразований — линейное преобразование. Из модуля 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\):

\[z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}, \qquad a^{(l)} = f(z^{(l)})\]

где \(a^{(0)} = x\) — вход, \(f\) — активация, а на последнем слое активации обычно нет: там сигмоида для двух классов, softmax для многих, ничего для регрессии.

Всё. Прямой проход — это цикл из двух строк.

Обратный проход

Теперь главное в модуле.

Нужны \(\partial L/\partial W^{(l)}\) для каждого слоя. Идём цепным правилом справа налево.

Введём \(\delta^{(l)} = \partial L / \partial z^{(l)}\) — насколько потеря чувствительна к входу активации слоя \(l\). Через эту величину всё выражается коротко.

Последний слой. Для пары «сигмоида плюс log loss» из модуля 5 всё сокращается:

\[\delta^{(L)} = a^{(L)} - y\]

Та же формула \((p - y)\), что была там. Сокращение не случайно: функцию потерь и последнюю активацию подбирают в пару именно ради него.

Шаг назад через слой. Зная \(\delta^{(l)}\), получаем предыдущую:

\[\delta^{(l-1)} = \left( W^{(l)\mathsf{T}} \delta^{(l)} \right) \odot f'(z^{(l-1)})\]

Читается по частям. \(W^{\mathsf{T}}\delta\) — ошибка, разложенная обратно по нейронам предыдущего слоя пропорционально весам, которыми они на неё повлияли. \(\odot f'\) — поэлементное домножение на производную активации: нейрон в насыщении почти не влияет, значит и виноват почти не он.

Градиенты параметров.

\[\frac{\partial L}{\partial W^{(l)}} = \delta^{(l)} a^{(l-1)\mathsf{T}}, \qquad \frac{\partial L}{\partial b^{(l)}} = \delta^{(l)}\]

Первая формула — та же структура «ошибка умножить на вход», что была у логистической регрессии в модуле 4. Она не изменилась, просто теперь применяется к каждому слою.

Что такое backprop на самом деле

Обратное распространение — это не алгоритм обучения. Это способ посчитать градиент за один проход вместо \(N\) проходов, где \(N\) — число параметров.

Обучает по-прежнему градиентный спуск из модуля 4. Backprop только доставляет ему градиент, и его единственная заслуга — эффективность: он переиспользует уже посчитанные \(\delta\) вместо того, чтобы считать производную по каждому весу заново.

Наивный численный градиент для сети с миллионом параметров потребовал бы два миллиона прямых проходов на каждый шаг. Backprop обходится одним прямым и одним обратным.

Инициализация

Вопрос, который выглядит техническим и решает, будет ли сеть учиться вообще.

Нулями нельзя. Если все веса слоя равны, все его нейроны получают одинаковый вход, дают одинаковый выход и получают одинаковый градиент. Они остаются одинаковыми навсегда. Слой из ста нейронов работает как один. Это называется проблемой симметрии, и ломается она только случайностью.

С нулями конкретно всё ещё резче. Градиент первого слоя идёт назад через веса второго — формула \(W^{\mathsf{T}}\delta\) выше, — а они нулевые. Значит он тождественно ноль, и первый слой не двигается вообще, ни на шаг. В ноутбуке это видно: после трёхсот шагов все его веса по-прежнему ровно нули.

Слишком большими нельзя. Активации растут от слоя к слою, сигмоида уходит в насыщение, её производная падает почти до нуля — обучение стоит.

Слишком маленькими нельзя. Сигнал затухает по глубине и до последних слоёв доходит шум.

Рабочее правило — держать дисперсию сигнала постоянной по слоям. Отсюда два стандарта:

\[\text{Xavier: } \mathrm{Var}(W) = \frac{1}{n_{\text{вход}}}, \qquad \text{He: } \mathrm{Var}(W) = \frac{2}{n_{\text{вход}}}\]

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.

Что внутри:

  1. XOR: линейная модель не может, сеть с одним скрытым слоем может. Видно границу решения.
  2. Слой как объект: прямой проход в три строки.
  3. Обратный проход и его gradient check. Затем — намеренно испорченная формула, чтобы увидеть, как проверка её ловит.
  4. Инициализация: нулями, слишком большая, He. Три кривых обучения.
  5. Затухание градиента по глубине: сигмоида против ReLU, градиент первого слоя в числах.
  6. Сеть против бустинга на табличных данных модуля 6, с интервалами.

Часть 2. Своя сеть

  1. Добавьте в код ноутбука ещё одну активацию — tanh или Leaky ReLU.
  2. Проверьте её gradient check. Пока не сошлось — не обучайте.
  3. Постройте кривые обучения для трёх активаций на одних данных и зёрнах.
  4. Найдите глубину, на которой сигмоидная сеть перестаёт учиться совсем. Посчитайте градиент первого слоя и сравните с \(0.25^{\text{глубина}}\).

Задание

  1. Выведите на бумаге \(\delta^{(l-1)}\) через \(\delta^{(l)}\). Не подглядывая в текст.
  2. Докажите, что два линейных слоя без активации эквивалентны одному. Двух строк достаточно.
  3. Реализуйте softmax и кросс-энтропию для нескольких классов. Покажите, что \(\delta^{(L)}\) снова равна \(a - y\).
  4. Инициализируйте сеть нулями и покажите численно, что все нейроны скрытого слоя остаются одинаковыми после ста шагов.
  5. Возьмите свою табличную задачу из модуля 6 и повторите сравнение с бустингом честно. Запишите вывод в формате модуля 1: величина, условия, база.

Пятый пункт — тот же, что был в модуле 6, и это намеренно. Теперь у вас на одну модель больше, а правила сравнения не изменились.

Проверка себя

  1. Почему без нелинейности глубина не даёт ничего?
  2. Чему равен максимум производной сигмоиды и что из этого следует для глубоких сетей?
  3. Что такое \(\delta^{(l)}\) на словах?
  4. Объясните \(W^{\mathsf{T}}\delta\) и поэлементное умножение на \(f'\) по отдельности.
  5. Backprop — это алгоритм обучения? Если нет, то что?
  6. Почему нельзя инициализировать веса нулями?
  7. Откуда в инициализации He двойка?
  8. Сеть проиграла бустингу на таблице. Какой из этого вывод, а какой — нет?

Дальше

В модуле 9 появляются свёртки — первая архитектура, которая использует структуру данных, а не просто перемалывает признаки. Там же сеть впервые выиграет у бустинга, и выиграет с большим отрывом.

Нейросеть — это композиция линейных слоёв, склеенная цепным правилом. Умение её обучить не означает, что её надо обучать.