Если открыть случайную научную статью по глубинному обучению и попробовать воспроизвести её результаты, можно запросто потерпеть крах, и даже код на github, если он есть, может не помочь.
А дело в том, что обучение сложной модели — это сложная инженерная задача, в которой успеху сопутствует огромное число разных хаков, и изменение какого-нибудь безобидного параметра может очень сильно повлиять на результат.
В этом параграфе мы познакомим вас с некоторыми из таких приёмов.
Инициализируем правильно
Как вы уже успели заметить, нейронные сети — достаточно сложные модели, чувствительные к изменениям архитектуры, гиперпараметров, распределения данных и другим вещам.
Поэтому значительную роль играет начальная инициализация весов вашей сети. Стоит отметить, что здесь речь идет именно о начальной инициализации параметров сети, вопрос дообучения (и использования предобученных сетей в качестве backbone) в данном параграфе рассматриваться не будет.
Нейронные сети включают в себя различные преобразования, и инициализация по-хорошему также должна зависеть от типа используемого преобразования. На практике вопрос часто остается без внимания, так как в большинстве современных фреймворков уже реализованы методы инициализации, зависящие от используемой функции активации и гиперпараметров слоя, и пользователь может не задумываться об этом. Но всё же важно понимать, какие соображения привели к появлению тех или иных стратегий инициализации.
Давайте разберём несколько методов инициализации и обсудим их свойства.
Наивный подход №0: инициализация нулем/константой
Казалось бы, инициализация параметров слоя нулями — это достаточно просто и лаконично. Но инициализация нулём (как и любой другой константой) ведёт к катастрофе! Вот пример того, что может получиться:
Стоит, впрочем, отметить, что из-за численных ошибок значения параметров могут всё-таки сдвинуться с мёртвой точки, и тогда нейросеть что-нибудь выучит:
Математическая иллюстрация того, почему плохо инициализировать нулями
Нам понадобится сеть с хотя бы двумя слоями (иначе ничего не получится).
Рассмотрим несколько последовательных скрытых представлений:
- ;
- , где — матрица весов, которую инициализировали нулями;
- , где — поэлементная нелинейность;
- , где — ещё одна инициализированная нулями матрица весов.
Проследим, что происходит во время forward pass.
Получилась снова матрица с одинаковыми столбцами, и это сохраняется дальше:
Теперь рассмотрим обратный проход. Допустим, мы вычислили градиент . Тогда
то есть матрица никак не обновится. Далее,
то есть веса тоже не обновятся. Таким образом, обучение происходить не будет.
А что же будет с однослойной нейросетью? Вспомним, что веса логистической регрессии (нейросети с одним-единственным, последним слоем) можно инициализировать чем угодно, в том числе нулями: функция потерь выпукла, поэтому градиентный спуск сходится из любой точки (по модулю численных эффектов).
Здесь также стоит привести цитату из замечательной Deep Learning book (страница 301):
Perhaps the only property known with complete certainty is that the initial parameters need to “break symmetry” between different units. If two hidden units with the same activation function are connected to the same inputs, then these units must have different initial parameters. If they have the same initial parameters, then a deterministic learning algorithm applied to a deterministic cost and model will constantly update both of these units in the same way.
Эвристический подход №1: инициализация случайными числами
Если константная инициализация не подходит, можно инициализировать нейросеть случайными числами. Допустим, веса пришли из распределения с нулевым средним и дисперсией , например, из нормального распределения .
Пусть теперь на вход линейному слою с весами размерности пришел вектор аналогичной размерности.
Замечание. Можем считать, что мы рассматриваем лишь одну компоненту следующего промежуточного представления .
Все компоненты распределены одинаковым образом и обладают нулевым средним. Тогда дисперсия их произведения имеет вид:
Первое и второе слагаемые равны нулю так как математические ожидание и весов, и значений равны нулю.
Замечание. Стоит заметить, что это будет верно и для промежуточных слоев в случае использования симметричной относительно нуля функции активации, например, tanh
.
Поскольку все веса пришли из одного распределения, можно выразить дисперсию результата следующим образом:
где — это дисперсия любой компоненты (как было оговорено ранее, они распределены одинаково), а — дисперсия компоненты .
Следовательно, дисперсия результата линейно зависит от дисперсии входных данных с коэффициентом .
Увеличение дисперсии промежуточных представлений с каждым новым преобразованием (слоем) может вызвать численные ошибки или насыщение функций активации (таких как tanh
и sigmoid
), что не лучшим образом скажется на обучении сети.
Снижение дисперсии может привести к почти нулевым промежуточным представлениям (плюс «линейному» поведению tanh
и sigmoid
в непосредственной близости от нуля), что тоже негативно повлияет на результаты обучения.
Поэтому для начальной инициализации весов имеет смысл использовать распределение, дисперсия которого позволила бы сохранить дисперсию результата. Например, или же в общем случае
Данный подход часто упоминается как calibrated random numbers initialization
.
Подход №2: Xavier & Normalized Xavier initialization
Если обратиться к предыдущему подходу, можно обнаружить, что все выкладки верны как для «прямого» прохода (forward propagation), так и для обратного (backward propagation). Дисперсия градиента при этом меняется в раз, где — размерность следующего за промежуточного представления.
И если мы хотим, чтобы сохранялись дисперсии и промежуточных представлений, и градиентов, у нас возникают сразу два ограничения:
и
Легко заметить, что оба этих ограничения могут быть выполнены только в случае, когда размерность пространства не меняется при отображении, что случается далеко не всегда.
В работе Understanding the difficulty of training deep feedforward neural networks за авторством Xavier Glorot и Yoshua Bengio в качестве компромисса предлагается использовать параметры из распределения с дисперсией
Подробный вывод данного результата можно найти в оригинальной статье в формулах 2-12.
Обратите внимание: эта инициализация хорошо подходит именно для tanh
, так как в выводе явно учитывается симметричность функции активации относительно нуля.
В случае использования равномерного распределения для инициализации весов с учетом описанных выше ограничений мы получим normalized Xavier initialization:
Замечание. Здесь используется тот факт, что дисперсия непрерывного равномерного распределения .
Сравнение подобной инициализации для поведения промежуточных представлений (сверху) и градиентов (снизу) проиллюстрированы ниже (иллюстрации из оригинальной статьи):
Подход №3: Kaiming initialization
Вы могли обратить внимание, что Xavier initialization во многом опиралась на поведение функции активации tanh
. Данный тип инициализации и впрямь лучше подходит для нее, но само использование гиперболического тангенса приводит к некоторым сложностям (например, к затуханию градиентов).
В 2015 году в работе Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification за авторством Kaiming He, Xiangyu Zhang, Shaoqing Ren и Jian Sun были рассмотрены особые свойства функции активации ReLU
, в частности, существенно смещенная относительно нуля область значений.
Пусть представление на входе было получено после применения данной функции активации к предыдущему представлению :
где , в свою очередь, — это выход предыдущего линейного слоя с нулевым средним для каждой компоненты весов, то есть, в частности,
В таком случае дисперсия выхода следующего линейного слоя примет вид:
В данном случае первый член не может быть проигнорирован, так как ReLU
имеет ассиметричную область значений, а значит, распределения будут смещёнными.
С учетом того, что , выражение выше примет итоговый вид:
С учётом поведения ReLU
и того, что , можно сказать, что
то есть
Получается, что использование ReLU
приводит к необходимости инициализировать веса из распределения, чья дисперсия удовлетворяет следующему ограничению:
Например, подходит нормальное распределение .
Данный способ инициализации (и его сравнение с Xavier initialization) проиллюстрирован ниже:
Промежуточные выводы
Рассмотренные способы инициализации используют достаточно много предположений, но все-таки они работают и позволяют нейронным сетям в некоторых случаях значительно быстрее сходиться.
Понимание принципов работы даже таких небольших механизмов – ключ к глубокому освоению области глубокого обучения 😃
Методы оптимизации в нейронных сетях
Так как мы договорились, что нейросети представляют собой параметризованные дифференцируемые функции и для каждого параметра мы можем посчитать градиент, то, так же как и линейные модели, их можно настраивать с помощью градиентных методов.
В параграфе про линейные модели мы под этим подразумевали обычно стохастический градиентный спуск на батчах, и это совершенно подходящий способ и для нейросетей тоже. Но существует множество модификаций и эвристик, позволяющих ускорить его сходимость, познакомиться с которыми вы можете в специальном параграфе, посвящённом методам оптимизации.
Регуляризация нейронных сетей
Смысл термина регуляризация (англ. regularization) гораздо шире привычного вам прибавления - или -нормы вектора весов к функции потерь. Фактически он объединяет большое количество техник для борьбы с переобучением и для получения более подходящего решения с точки зрения эксперта.
Каждая из них позволяет навязать модели определённые свойства, пусть даже и ценой некоторого снижения качества предсказания на обучающей выборке. Например, уже знакомая читателю - или -регуляризация в задаче линейной регрессии (регуляризация Тихонова) позволяет исключить наименее значимые признаки (для линейной модели) или же получить устойчивое (хоть и смещённое) решение в случае мультиколлинеарных признаков.
В нейронных сетях техники регуляризации можно разделить на три обширные группы:
- связанные с изменением функции потерь;
- связанные с изменением структуры сети;
- связанные с изменением данных.
Рассмотрим каждую из них подробнее.
Регуляризация через функцию потерь
Изменение функции потерь — классический способ получить решение, удовлетворяющее определённым условиям. В глубинном обучении часто используется техника Weight Decay, очень близкая к регуляризации Тихонова. Она представляет собой аналогичный штраф за высокие значения весов нейронной сети с коэффициентом регуляризации :
Данная техника регуляризации была совмещена с методом градиентной оптимизации Adam, в результате чего был получен метод AdamW (описанный в параграфе параграфе про методы оптимизации).
Также достаточно часто в качестве регуляризационного члена встречается энтропия распределения, предсказанного нейронной сетью.
Представьте, что вы рекомендуете пользователю товары по истории его взаимодействия с сервисом, семплируя товары для показа в соответствии с распределением предсказанной релевантности. Вам может быть важно, чтобы рекомендации не были фиксированными (менялись при обновлении страницы), ведь это повысит вероятность того, что пользователь найдёт что-то интересное, а вы узнаете о нём что-нибудь новое.
В такой ситуации при обучении модели вы можете потребовать, чтобы распределение предсказаний не сходилось к вырожденному, и в качестве дополнительной штрафной функции может выступать энтропия этого распределения. Энтропия дифференцируема, как и сами предсказанные величины, и может быть использована в качестве регуляризационного члена. Для задачи классификации он будет выглядеть следующим образом:
где — коэффициент регуляризации, — предсказанные вероятности.
Тем самым эксперт привносит своё знание непосредственно в процесс обучения модели в подходящей математической форме: «предсказания должны быть разнообразными» —> «распределение не должно быть вырожденным» —> «энтропия не должна быть слишком низкой».
Регуляризация через ограничение структуры модели
Внесение подходящих преобразований в структуру сети также может быть хорошим способом добиться желаемых результатов. Огромное влияние на развитие нейронных сетей оказали техники dropout (2014) и batch normalization (2015), позволившие сделать нейронные сети более устойчивыми к переобучению и многократно ускорить их сходимость соответственно.
Dropout
Обратимся к простым полносвязным (FC/Dense) сетям из нескольких слоёв. Каждый из слоёв порождает новое признаковое описание объекта , который пришёл на вход:
Но как можно гарантировать, что модель будет эффективно использовать все доступные параметры, а не переобучится под использование лишь небольшого их подмножества, поделив для себя внутреннее представление на сигнал и шум?
Для этого можно было бы случайным образом «выключать» доступ к некоторым координатам внутренних представлений на этапе обучения. Тогда при выключении «полезных» координат произойдёт резкое изменение предсказаний модели, что приведёт к увеличению ошибки, а полученные градиенты этой ошибки укажут, как её исправить с использованием (и изменением) других координат. Сравнение тока информации по исходной модели и по модели с «выключенными» координатами внутренних представлений можно проиллюстрировать с помощью классической картинки:
Обратите внимание: «выключать» можно как оригинальные признаки, так и признаки, возникающие на любом другом уровне представления объектов. С точки зрения -го слоя нейронной сети данные приходят откуда-то извне: при — из реального мира, а при — с предыдущих слоёв.
Технически это осуществляется следующим образом: некоторые координаты внутреннего представления домножаются на ноль. То есть добавляется ещё одно преобразование, которое представляет собой домножение выхода предыдущего слоя на маску из нулей и единиц.
где (вероятность обнуления координаты) — это гиперпараметр слоя. Отметим, что во многих фреймворках для глубинного обучения в качестве параметра слоя указывается именно вероятность обнуления, а не выживания. Данная маска участвует и при подсчёте градиентов:
Как правило, маска генерируется независимо на каждом шаге градиентного спуска. Важно отметить, что на этапе предсказания dropout ничего не меняет, то есть .
Множитель нужен для того, чтобы распределение на этапе предсказания совпадало с распределением на этапе обучения. В самом деле, если даже математическое ожидание было равно нулю, выборочная дисперсия ниже, чем у : ведь часть значений обнулилась.
На этапе предсказания dropout «выключается»: внутренние представления используются как есть, без умножения на маску. А чтобы слой знал, обучается он сейчас или предсказывает, в нейросетевых библиотеках в классе слоя обычно реализовано переключение между этими режимами (например, булев флаг training
в pytorch-модулях).
Примечание
Полезно провести аналогию с другим алгоритмом, использующим техники ансамблирования и метод случайных подпространств: речь о случайном лесе (Random Forest). При обучении сети на каждом шаге обучается лишь некоторая подсеть (некоторый подграф вычислений из исходного графа). При переходе в режим inference (то есть применения к реальным данным с целью получения результата, а не обучения) активируются сразу все подсети, и их результаты усредняются. Таким образом, сеть с dropout можно рассматривать как ансамбль из экспоненциально большого числа сетей меньшего размера (подробнее можно прочитать здесь). Это приводит к получению более устойчивой оценки значений целевой переменной.
В этом свойстве кроется и главное коварство dropout (как и большинства других техник регуляризации): благодаря получению более устойчивой оценки целевой переменной путём усреднения множества подсетей, эффективная обобщающая способность итоговой сети снижается! В самом деле, пусть при обучении каждый раз модели была доступна лишь половина параметров. В таком случае итоговая модель представляет собой усреднение множества более слабых моделей, в которых вдвое меньше параметров. Её предсказания будут более устойчивы к шуму, но при этом она неспособна выучить столь сложные зависимости, как сеть аналогичной структуры, но без dropout. То есть за более устойчивые предсказания (и получение менее переобученной модели) приходится расплачиваться и меньшей обобщающей способностью.
Стоит отметить, что dropout может применяться и к входным данным (то есть слой dropout может стоять первым в сети), и это может приводить к получению более качественных результатов. Например, если в данных множество мультикоррелирующих признаков или присутствует шум, наличие dropout позволит избежать обусловливания модели на лишь их подмножество и позволит учитывать их все. Так, подобный подход может быть использован, если данные представляют собой сильно разреженные векторы высокой размерности (скажем, сведения об интересе пользователя к тем или иным товарам).
Batch normalization
Появление техники batch normalization привело к значительному ускорению обучения нейронных сетей. В данном параграфе мы рассмотрим лишь основные принципы работы batch normalization.
Дискуссия о свойствах и причинах эффективности batch normalization всё ещё ведётся, рекомендуем обратить внимание на статью с NeurIPS 2018. Нам, впрочем, кажется, что, несмотря на активную критику в его адрес, полезно знать и предложенное авторами подхода объяснение необходимости batch normalization.
Предложенная авторами мотивация
Обратимся к механизму обратного распространения ошибки. Пусть мы находимся на этапе обновления параметров некоторого -го слоя:
где — некоторая функция, которая вычисляется на данном слое. В общем случае и не обязательно взаимодействуют линейным образом; функция может быть и нелинейной. В ходе error backward propagation мы вычисляем градиент:
где — некоторая функция, в которой будут участвовать представления со слоёв, начиная с -го (вычисленные в ходе forward pass и запомненные).
Новое значение параметров примет вид:
После обновления параметров мы перейдём к обновлению параметров предыдущего слоя и обновим их аналогичным образом.
Важно. Это приведёт к изменению представления, которое пришло на вход -му слою, которое мы не учитываем:
где — разница между предыдущими и новыми параметрами .
То есть параметры -го слоя будут обновлены исходя из предположения, что данные приходят из некоторого распределения на , которое параметризовалось , но теперь параметры изменились и данные могут обладать иными свойствами. Например, может существенно измениться среднее или дисперсия, что может привести, например, к попаданию на «хвосты» функции активации и затуханию градиента.
До появления batch normalization с этой проблемой боролись достаточно просто: использовали небольшие значения шага обучения (learning rate) . Благодаря этому изменения были не слишком большими и можно было предположить, что и распределение внутренних представлений поменялось незначительно.
Использование batch normalization гарантирует, что каждая компонента представления на выходе будет иметь контролируемое среднее и дисперсию. Достигается это следующим образом:
- Сперва идёт собственно слой batch normalization, на котором текущий батч приводится к нулевому среднему и единичной дисперсии:
где и — среднее и дисперсия признаков по обрабатываемому батчу, а — гиперпараметр слоя, небольшое положительное число, добавляемое для улучшения численной устойчивости. Отметим, что и , будучи функциями от , тоже участвуют в вычислении градиентов. В ходе предсказания (или, как ещё говорят, инференса, от английского inference) используются фиксированные значения и , которые были получены в ходе обучения как скользящее среднее всех и . Более точно: на каждой итерации forward pass мы вычисляем
где также является гиперпараметром слоя.
- Далее идёт слой channelwise scaling, который позволяет выучить оптимальное шкалирование для всех признаков :
где и — обучаемые параметры, позволяющие настраивать в ходе обучения оптимальные значения матожидания и дисперсии выходного слоя .
Ниже приведён алгоритм из оригинальноq статьи 2015 года за авторством Сергея Иоффе и Кристиана Сегеди:
Причина популярности batch normalization заключается в значительном ускорении обучения нейронных сетей и в улучшении их сходимости в целом. Рассмотрим график из оригинальной статьи:
Как видно на иллюстрации выше, использование batch normalization позволило ускорить обучение в несколько раз и даже добиться лучших результатов, чем SotA-подход 2014 года Inception (структура которого была приведена на одной из иллюстраций в начале этого параграфа).
Значительное ускорение достигается в том числе благодаря использованию более высокого learning rate: благодаря нормировке связь между слоями не нарушается столь сильно.
Стоит заметить, что причины столь эффективной работы batch normalization до сих пор являются поводом для дискуссий и строгого теоретического объяснения эффекта от batch normalization ещё нет. Несмотря на это, он перевернул область глубинного обучения и вошёл в стандартный инструментарий при обучении нейронных сетей.
Примечание: стоит заметить, что в настоящее время существуют и другие способы нормировать промежуточные представления: instance normalization, layer normalization и так далее.
В завершение рекомендуем ознакомиться со статьёй о работе метода обратного распространения ошибки в слое batch normalization.
Регуляризация через изменение данных
Внесение изменений в данные (аугментация данных) также является популярной техникой регуляризации. Рассмотрим её на примере.
Пусть перед нами фотография самолёта. Добавим мелкодисперсный шум к изображению. Мы всё ещё сможем увидеть на фотографии самолёт, но, с точки зрения модели машинного обучения (в данном случае — нейронной сети), полученное изображение является новым объектом!
Повернём изображение самолёта на 10 градусов по часовой стрелке. В нашем распоряжении ещё одно изображение с известной целевой меткой (например, меткой класса «самолёт»), в котором присутствует поворот. Таким образом, внесение новых данных позволяет дать модели понять, какие преобразования над данными являются допустимыми, и она уже будет более устойчивой к наличию небольшого шума в данных или к поворотам (к которым чувствительна операция свёртки).
Вдобавок аугментации позволяют значительно увеличить объём обучающей выборки. Особую популярность аугментации приобрели в области компьютерного зрения. В качестве примера приведём отличную библиотеку, позволяющую производить аугментацию изображений.
Стоит обратить внимание, что используемые аугментации должны быть адекватны решаемой задаче. Инвертирование цветов на фотографии, внесение значительного количества шумов или переворот изображения могут привести и к негативным результатам (по сути, просто сделают выборку более зашумлённой или даже заставят сеть учиться на данных, которые она никогда не встретит в реальности), так как обобщающая способность сети ограниченна. Можно сказать, что аугментированные данные должны принадлежать к той же генеральной совокупности, что и оригинальный датасет.
Итак, эксперт может привнести своё понимание задачи и на уровне аугментации данных: если данное преобразование является допустимым (то есть преобразованный объект мог бы попасть в обучающую выборку и самостоятельно — как фотография с другого устройства или запись речи другого человека с опечаткой), то модель должна быть устойчива к данным с подобными преобразованиями.