ResNet - революция глубокого обучения. Исчезающие и взрывающиеся градиенты

На предыдущем занятии мы с вами построили относительно простую нейронную сеть для классификации изображений БД CIFAR-10 и получили качество распознавания на уровне 72%. Было бы хорошо улучшить этот показатель. Один из способов – построить более глубокую сеть. Но, чтобы это грамотно сделать, нужно познакомиться с уже существующими глубокими сетями и знать особенности их построения и обучения. Именно такой краткий обзор мы сделаем на этом занятии. А на следующем применим эти знания для построения и обучения глубокой сети, построенной по принципу сети ResNet.

Нейросети VGG-16 и VGG-19

В 2014-м году на соревнованиях по компьютерному зрению группа из Оксфордского университета представила сетьVGG-16 (сокращение от VisualGeometryGroup), а 16 – это общее число слоев. При классификации БД изображений ImageNet она показала качество в 92,7%. Для нейронных сетей того времени это было значительным достижением. В действительности, это одна из первых сетей, которую можно отнести к глубоким сетям, так как она содержала 16 слоев:

Главным новшеством этой сети стало использование последовательно идущих сверточных слоев с ядрами сверток 3x3 элемента. Благодаря этому получался охват области в 5x5 элементов (для двух слоев), но число параметров заметно меньше (20 против 26):

Если же взять три подряд сверточных слоя с фильтрами 3x3, то получим охват 7x7 элементов и еще больший выигрыш по числу коэффициентов. Кроме того, как показали эксперименты, такой подход улучшает обобщающие свойства сети и ускоряет обучение. Эта идея стала настолько популярной, что NVIDIA в очередном релизе библиотеки cuDNN специально оптимизировала работу с такими свертками.

Давайте еще раз внимательно посмотрим на эту архитектуру. Во-первых, мы видим, что слои со свертками 3x3 идут друг за другом без каких-либо нелинейностей. То есть, выходы со сверток первого слоя без изменений поступают на вход следующего слоя. Во-вторых, по мере движения в глубину увеличивается число каналов в сверточных слоях. В-третьих, последний нелинейный слой пропускается через полносвязную сеть для формирования выходного вектора.

По аналогии образована архитектура сети VGG-19. В таблице ниже представлены обе структуры VGG:

VGG-16

VGG-19

input (224x244x3)

conv3-64

conv3-64

conv3-64

conv3-64

maxpool

conv3-128

conv3-128

conv3-128

conv3-128

maxpool

conv3-256

conv3-256

conv3-256

conv3-256

conv3-256

conv3-256

conv3-256

maxpool

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

maxpool

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

conv3-512

maxpool

FC-4096

FC-4096

FC-1000

softmax

Фактически, с сети VGG началась эпоха глубокого обучения (deeplearning). Благодаря блокам последовательных слоев без нелинейностей между ними, появилась возможность конструировать и эффективно обучать сети более чем 10 слоев. При этом, качество распознавания впервые достигло, а потом и превзошло человеческий уровень. Так, современные нейронные сети выполняют классификацию изображений БД CIFAR-10 на уровне 96,5%, тогда как человек решает эту же задачу с точностью около 94%.

Исчезающие и взрывающиеся градиенты

Но почему работающие глубокие нейронные сети появились лишь в начале 2000-x, а не раньше в 1980-x, когда активно развивалось это направление? Здесь есть две главные причины. Первая, конечно же, связана с недостаточными вычислительными мощностями первых компьютеров. Глубокие сети содержат очень много настраиваемых параметров и алгоритм градиентного спуска требует большого объема и вычислений и памяти. По существу, в 1980-х не было ни того, ни другого. Только в середине 2000-х графические процессоры с их параллельными вычислениями дали реальный инструмент для обучения глубоких нейронных сетей.

Вторая проблема математическая. Если взять НС с большим числом слоев и применить к ней алгоритм обратного распространения ошибки (backpropagation), то обучение будет проходить неравномерно. Последние слои (те, что ближе к выходу) будут обучаться быстрее начальных. В результате, ошибка на выходе будет стремиться к нулю и, как следствие, градиенты также будут принимать малые значения. А величина градиента, как мы знаем, влияет на величину изменения весовых коэффициентов, согласно общей формуле градиентного спуска:

Это значит, что хорошо обученные последние слои «блокируют» обучение начальных слоев и алгоритм обратного распространения, фактически, застревает на определенном уровне, как правило, далеко не оптимальном. Все это теперь известно под названием проблема затухающих градиентов (vanishing gradients).

Существует и обратный процесс, характерный для рекуррентных сетей (сетей с обратными связями). Он связан с неконтролируемым ростом градиента, так как в рекурсии используются одни и те же весовые коэффициенты, а значит, небольшое увеличение градиента на первой итерации будет постоянно увеличиваться на последующих. Этот эффект получил название взрывающиеся градиенты (exploding gradients).

Одно из первых решений преодоления проблем с градиентами стало предобучение фрагментов нейронной сети. Грубо говоря, вся сеть разбивалась на несколько независимых частей, каждая часть представляла собой уже обычную не глубокую нейронную сеть и могла быть обучена до некоторого начального уровня. При этом использовался метод обучения без учителя, например, на основе ограниченных машин Больцмана (так делала группа под руководством британского ученого Джеффри Хинтона). А, затем, запускался алгоритмдообучения для всей сети стандартным способом.

Джеффри Хинтон

Однако сейчас эта техника почти не используется, но она позволила лучше понять направления дальнейших исследований для поиска решений обучения глубоких сетей. Как результат, были предложены эффективные методы начальной инициализации весов, благодаря работам Ян Ле Куна, Йошуа Бенджи и Хавьера Глоро. А два сотрудника Google Иоффе и Сегеди в 2015-м предложили алгоритм батч-нормализации (BatchNormalization) для ускорения сходимости алгоритма градиентного спуска. Благодаря этим разработкам, а также различным оптимизаторам самого градиентного алгоритма, проблема исчезающих градиентов отошла на второй план.

Глубокое остаточное обучение

Значит, получается, что мы теперь можем строить сколь угодно большие нейронные сети и обучать их с использованием разработанных методов оптимизации? Как показала практика, не все так просто. При обучении глубоких архитектур их эффективность часто оказывалась хуже менее глубоких моделей. Причем, с добавлением новых слоев ошибка росла и на тестовом и на тренировочном множествах, то есть, это не проблема переобучения, а именно ухудшение эффективности сети в целом. Хотя, казалось бы, более глубокая модель – частный случай менее глубокой и такой проблемы быть не должно. Но она возникает. Вывод здесь один – недостаточная эффективность современных алгоритмов обучения.

Что же получается, мы по-прежнему не можем по-настоящему обучать глубокие нейронные сети с сотнями слоев? В действительности, да, это проблема, которая ждет своего решения. И пока нет другого, более эффективного алгоритма обучения, чем back propagation, команда из Microsoft Research предложила оригинальный подход для построения архитектуры глубоких сетей, которые можно обучать и современными методами.

Новая идея получила название глубокое остаточное обучение (deep residual learning), которое легло в основу сети ResNet. Эта сеть состоит из блоков, со стандартными слоями, идущими друг за другом, обычно, включающиетакже слой BatchNormalization (нормализацию по мини-батчам),но у этого блока есть «обходной путь», который напрямую связывает вход с выходом. В результате, выходное значение блока формируется, как:

В чем может быть преимущество такого подхода? Смотрите, предположим, этот блок должен аппроксимировать некоторую функцию  (то есть, описать некоторые характеристики). Другими словами, мы хотим, чтобы выходное значение описывалось функцией:

Отсюда автоматически получается, что

То есть, слои, составляющие функцию  должны аппроксимировать не всю функцию  целиком, а лишь ее остаток. Отсюда и пошло название таких моделей – остаточные сети (residual networks). А блок, соответственно, называют остаточным блоком. В таком блоке нам достаточно обучить сеть воспроизводить не весь сигнал целиком, а лишь отличия входных значений для получения требуемой функции.

Как показала практика, обучить «остаточную» функцию гораздо проще, чем исходную. Это также связано с тем, что градиент для остаточного блока принимает вид:

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

Конечно, существует множество вариантов сети ResNet, где к обходному пути добавляются различные гейты (управляющие слои) для регулирования передаваемых «обходных» данных . Это особенно актуально в рекуррентных сетях. Но для не рекуррентных архитектур обычный «обходной» путь, как правило, показывает хорошие результаты, зачастую даже лучшие, чем другие модифицированные варианты.

Каймин Хе назвал это «революцией глубины». В сетях VGG-16 и VGG-19 было всего 16 и 19 слоев. В сети GoogLeNet – 22 слоя, а в первом варианте ResNet – 152 слоя. Сейчас это число доходит до тысяч уровней в глубину. И это не просто набор слоев, которые мы можем обучать. Они позволяют получать недостижимые ранее результаты. Например, в задачах распознавания образов, как правило, используют тот или иной вариант модификации сети ResNet. И на следующем занятии, мы как раз реализуем упрощенную модель такой сети для задачи классификации изображений БД CIFAR-10.

Видео по теме