Базовое описание того, как работает ResNet, и практический подход к пониманию современной сети.

При реализации архитектуры ResNet в проекте глубокого обучения, над которым я работал, это был огромный скачок по сравнению с базовыми, простыми сверточными нейронными сетями, к которым я привык.

Одной из характерных особенностей ResNet является то, что он использует микроархитектуру внутри своей более крупной макроархитектуры : остаточных блоков!

Я решил сам изучить модель, чтобы лучше понять ее, а также выяснить, почему она оказалась настолько успешной на ILSVRC. Я реализовал тот же самый класс модели ResNet в Глубокое обучение компьютерного зрения с помощью Python доктора Адриана Роузброка [1] ,, который следует модели ResNet из ResNet 2015 года. академическая публикация Deep Residual Learning for Image Recognition He et al. [2].

ResNet

Когда ResNet был впервые представлен, он был революционным для доказательства нового решения огромной проблемы для глубоких нейронных сетей того времени: проблема исчезающего градиента. Хотя нейронные сети являются универсальными аппроксиматорами функций, при определенном пороге добавление большего количества слоев замедляет обучение и приводит к насыщению точности.

Это связано с обратным распространением градиентов при переходе от последних слоев к самым ранним - многократное умножение числа от 0 до 1 делает его все меньше: таким образом, градиент начинает «исчезать» при достижении более ранних слоев. Это означает, что более ранние слои не только медленнее обучаются, но и более подвержены ошибкам. Это огромная проблема, поскольку самые ранние уровни являются строительными блоками всей сети - они отвечают за определение основных, основных функций!

Чтобы смягчить эту проблему, ResNet включает быстрые соединения идентификации, которые по существу пропускают обучение одного или нескольких уровней, создавая остаточный блок.

Затем авторы предложили «оптимизированный» остаточный блок, добавив расширение, называемое узким местом. Это уменьшит размерность в первых двух слоях CONV (1/4 фильтров, полученных в последнем слое CONV), а затем снова увеличится во время последнего слоя CONV. Вот два остаточных модуля, уложенных друг на друга.

Наконец, He et al. опубликовал вторую статью об остаточном модуле под названием Сопоставления идентификационных данных в глубоких остаточных сетях, в котором представлена ​​еще лучшая версия остаточного блока: остаточная модель до активации. Это позволяет градиентам беспрепятственно распространяться через соединения быстрого доступа к любому из более ранних слоев.

Вместо того, чтобы начинать со свертки (веса), мы начинаем с ряда (BN = ›RELU =› CONV ) * N слоев (при условии, что используется узкое место). Затем остаточный модуль выводит операцию сложения , которая вводится в следующий остаточный модуль в сети (поскольку остаточные модули накладываются друг на друга).

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

Приступим к написанию кода реальной сети на Python. Эта конкретная реализация была вдохновлена ​​как He et al. в их дистрибутиве Caffe и реализации mxnet от Wei Wu.

Мы собираемся написать его как класс (ResNet), чтобы мы могли использовать его позже при обучении модели глубокого обучения.

Мы начинаем со стандартного импорта CNN, а затем приступаем к созданию нашей функции Остаточный_модуль. Взгляните на параметры:

  • данные: ввод в остаточный модуль
  • K: количество фильтров, которые будут изучены последним слоем CONV (первые два слоя CONV будут изучать фильтры K / 4).
  • шаг: контролирует шаг свертки (поможет нам уменьшить пространственные размеры без использования максимального объединения).
  • chanDim: определяет ось, которая будет выполнять пакетную нормализацию.
  • красный (т.е. уменьшить) будет контролировать, уменьшаем ли мы пространственные размеры (Истина) или нет (Ложь), поскольку не все остаточные модули будут уменьшать размеры нашего пространственного объема.
  • reg: применяет силу регуляризации ко всем слоям CONV в остаточном модуле.
  • bnEps: управляет Ɛ, отвечающим за предотвращение ошибок «деления на ноль» при нормализации входных данных.
  • bnMom: контролирует импульс для скользящей средней.

Теперь давайте посмотрим на остальную часть функции.

Сначала мы инициализируем (удостоверение) ярлык (соединение), который на самом деле является просто ссылкой на входные данные. В конце остаточного модуля мы просто добавляем ярлык к выходным данным нашей ветви предварительной активации / узкого места (строка 3).

В строках 6–9 первый блок модуля ResNet следует шаблону BN == ›RELU ==› CONV == ›. Слой CONV использует свертки 1x1 с помощью фильтров K / 4. Обратите внимание, что член смещения отключен для слоя CONV, поскольку смещения уже присутствуют в следующих слоях BN, поэтому нет необходимости во втором члене смещения.

Что касается узкого места, второй слой CONV изучает фильтры K / 4 размером 3 x 3.

Последний блок снова увеличит размерность, применяя фильтры K с размерами 1 x 1.

Чтобы избежать применения максимального объединения, нам нужно проверить, необходимо ли уменьшение пространственных размеров.

Если нам приказано уменьшить пространственные размеры, сверточный слой с шагом ›1 будет применен к ярлыку (строки 2–4).

Наконец, мы складываем ярлык и последний слой CONV, создавая вывод для нашего модуля ResNet (строка 7). Наконец-то у нас есть «строительный блок», чтобы начать построение нашей глубокой остаточной сети.

Приступим к созданию метода build.

Взгляните на параметры этапы и фильтры (оба являются списками). В нашей архитектуре (показанной выше) мы накладываем N остаточных модулей друг на друга (N = значение стадии). Каждый остаточный модуль на одном и том же этапе изучает одинаковое количество фильтров. После того, как на каждом этапе изучаются соответствующие фильтры, следует уменьшение размерности. Мы повторяем этот процесс, пока не будем готовы применить средний слой объединения и классификатор softmax.

Этапы и фильтры

Например, давайте установим этапы = (3, 4, 6) и фильтры = (64, 128, 256, 512). Первый фильтр (64) применяется к единственному уровню CONV, не являющемуся частью остаточного модуля - первому уровню CONV в сети. Затем три (stage = 3) остаточных модуля накладываются друг на друга - каждый из них изучит 128 фильтров. Пространственные размеры будут уменьшены, а затем мы складываем четыре (stage = 4) остаточных модуля друг над другом - каждый изучает 256 фильтров. Наконец, мы снова уменьшаем пространственные измерения и переходим к наложению друг на друга шести (stage = 6) остаточных модулей, каждый из которых изучает 512 фильтров.

Вернемся к созданию метода build.

Инициализируйте inputShape и chanDim в зависимости от того, используем ли мы порядок «каналы последние» или «каналы первые» (строки 3–4).

Как упоминалось выше, ResNet использует BN в качестве первого уровня в качестве дополнительного уровня нормализации вашего ввода (строки 2–4). Затем мы применяем CONV = ›, BN =› ACT = ›POOL, чтобы уменьшить пространственный размер (строки 7–13). Теперь давайте начнем накладывать остаточные слои друг на друга.

Чтобы уменьшить размер тома без использования слоев объединения, мы можем изменить шаг свертки. Первая запись на этапе будет иметь шаг (1, 1), что сигнализирует об отсутствии понижающей дискретизации. Затем на каждом этапе после этого мы будем применять остаточный модуль с шагом (2, 2), который будет уменьшать размер тома. Это показано в строке 5.

Затем мы перебираем количество слоев на текущем этапе (количество остаточных модулей, которые будут уложены друг на друга) в строках 10–13. Мы используем [i + 1] в качестве индекса в фильтрах, поскольку первый фильтр уже использовался. После того, как мы уложили остаточные модули стадий [i] друг на друга, мы возвращаемся к строкам 6–7, где уменьшаем пространственные размеры объема и повторяем процесс.

Чтобы избежать плотных полносвязных слоев, мы вместо этого применим средний пул, чтобы уменьшить размер тома до 1 x 1 x классов:

Наконец, мы создадим плотный слой для общего количества классов, которые мы собираемся изучить, а затем применим активацию softmax для генерации наших окончательных выходных вероятностей!

На этом наша функция сборки завершена, и теперь у нас есть полностью построенная модель ResNet! Вы можете обратиться к этому классу для реализации архитектуры ResNet в ваших проектах глубокого обучения.

Если у вас есть какие-либо вопросы, не стесняйтесь оставлять комментарии ниже или обращаться к нам!

использованная литература

[1] А. Роузброк, Глубокое обучение компьютерного зрения с помощью Python (2017)

[2] К. Хе, Х. Чжан, С. Рен и Дж. Сун, Глубокое остаточное обучение для распознавания изображений (2015), https://arxiv.org/abs/ 1512.03385