Или Об оврагах, долинах и трамплинах — КиберПедия 

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...

Или Об оврагах, долинах и трамплинах

2020-04-03 193
Или Об оврагах, долинах и трамплинах 0.00 из 5.00 0 оценок
Заказать работу

____________________ TL;DR___________________._______________________

Четвертая глава посвящена прогрессу в методах оптимизации и регуляризации нейронных сетей. Прогресс этот на первый взгляд незаметен, но во многом опре­деляет успех современных нейронных сетей. Мы рассмотрим:

• новейшие методы регуляризации, которые от сокращения весов перешли к дропауту и другим подходам;

• современные методы случайной инициализации весов, которые позволяют контролировать дисперсию выходов;

• метод нормализации по мини-батчам, который позволяет не обучать веса за­ново при изменении предыдущих слоев;

• улучшения градиентного спуска с помощью метода моментов;

• и даже адаптивные варианты градиентного спуска.


4.1. Регуляризация в нейронных сетях

Тем не менее изображенное на нем ничуть не отвечало совре­менности ни по духу, ни по замыслу, поскольку, при всей при­чудливости и разнообразии кубизма и футуризма, они редко вос­производят ту загадочную регулярность, которая таится в дои-* сторических письменах.

Г. Лавкрафт. Зов Ктулху

Эта глава будет посвящена тем видам прогресса в обучении нейронных сетей, ко­торые на первый взгляд кажутся незаметными. В самом деле, в разделе 2.5 мы го­ворили о том, что если мы можем определить структуру сети, то дальше задача как бы уже и решена, сведена к «всего лишь оптимизации», которую можно делать гра­диентным спуском, ведь мы же умеем брать производную от одного перцептрона, правильно? Таким образом, получается, что прогресс в области нейронных сетей должен выглядеть так: придумали новую архитектуру, засунули в «универсальный оптимизатор», в роли которого может выступить TensorFlow, посмотрели, не ста­ло ли лучше, придумали еще одну архитектуру, снова быстренько реализовали на TensorFlow...

И такой прогресс, конечно, есть. Многие главы этой книги будут посвящены именно разным архитектурам современных нейронных сетей. Однако в вышеупо­мянутой «всего лишь оптимизации» тоже кроется немало интересного. В настоя­щей главе мы поговорим о том, какие «трюки» позволяют нам обучать такие ги­гантские модели, как современные нейронные сети. Многие из этих трюков были придуманы совсем недавно, и можно сказать, что они тоже отделяют современную революцию нейронных сетей от того, как люди пытались обучать сети раньше. Мы уже говорили о том, что поначалу глубокие сети научились обучать с помощью до­статочно сложных моделей для предобучения без учителя, а потом оно снова стало не обязательным, — так вот, в этой главе мы узнаем, почему оно теперь больше не нужно.

Первая важная тема — регуляризация в нейронных сетях. В разделе 2.2 мы ви­дели, что модель, у которой слишком много свободных параметров, плохо обобща­ется, то есть слишком близко «облизывает» точки из тренировочного множества и в результате недостаточно хорошо предсказывает нужные значения в новых точ­ках. Современные нейронные сети — это модели с огромным числом параметров, даже не самая сложная архитектура может содержать миллионы весов. Значит, на­до регуляризовать.

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

Ь^-регуляризатор, сумму квадратов весов A Y2W 22»

L\-регуляризатор, сумму модулей весов Л Ml-

Разумеется, оптимизация от этого не сильно пострадает, ведь от регуляризато- ра тоже легко взять производную; просто немного изменится целевая функция.

В теории нейронных сетей такая регуляризация называется сокращением весов (weight decay), потому что действительно приводит к уменьшению их абсолютных значений. Его, конечно, применяли очень давно, в 1980-х годах уж точно [207,285]. И сейчас в таких библиотеках, как TensorFlow и Keras, вы тоже можете очень легко применить сокращение весов. Например, в Keras есть возможность для каждого слоя добавить регуляризатор на три вида связей:

• kernet_reguUarizer — на матрицу весов слоя;

• bias_reguUarizer — на вектор свободных членов;

• activity_regularizer — на вектор выходов.

Примерно так:

node■LaddlDensel256, input-dmrfZ, kernel_reguUarizer=reggUlrizers.11(0.001), bias_reguUarizer=reggUirizers.12(0.1), activi.ty_regu'larizer=reguUariLzers.12(0.01)))

Регуляризация в форме сокращения весов применяется до сих пор, однако сильно увлекаться подбором регуляризаторов мы не советуем.

Во-первых, есть еще один метод регуляризации, совсем простой и очевидный: давайте просто отложим часть тренировочного набора (назовем отложенную часть валидационным множеством) и будем при обучении на основном тренировочном множестве заодно вычислять ошибку и на валидационном. Предположение здесь в том, что ошибка на валидационном множестве будет хорошо оценивать ошибку и на новых точках (тестовом множестве), ведь она взята из данных той же при­роды, но тех, на которых мы не обучались. И остановить обучение нужно будет не тогда, когда сеть придет в локальный оптимум для тренировочного множества, а тогда, когда начнет ухудшаться ошибка на валидационном множестве. В теории нейронных сетей этот подход обычно называется методом ранней остановки (early stopping). Есть результаты о том, что ранняя остановка в некотором смысле эк­вивалентна Z/2-регуляризации [88]. В целом, вне зависимости от того, как именно вы будете делать раннюю остановку, мы в любом случае всецело рекомендуем от­ложить валидационную часть датасета и следить за ошибкой на этой части — это всегда полезно и дает хорошую оценку способности модели к обобщению. Если, конечно, размер датасета позволяет такую расточительность.

Во-вторых, в последние годы были разработаны более эффективные методы, которые стоит применить в первую очередь. При этом они часто работают настоль­ко хорошо, что до «обычного» сокращения весов дело может в итоге и не дойти. Од­ним из важнейших методов регуляризации нейронных сетей для революции глу­бокого обучения стал дропаут [129, 246].

Выходы '                                  У1                                                      Уг

Входы                                      Xi                                    х2

Рис. 4.1. Пример дропаута в трехслойной нейронной сети: на каждом новом

тренировочном примере структура сети изменяется

 

Его идея чрезвычайно проста.. Давайте для каждого нейрона (кроме самого по­следнего, выходного слоя) установим некоторую вероятность р, с которой он бу­дет... выброшен из сети. Алгоритм обучения меняется таким образом: на каждом новом тренировочном примере х мы сначала для каждого нейрона бросаем монет­ку с вероятностью р, и в зависимости от результата монетки.либо используем ней­рон как обычно, либо устанавливаем его выход всегда строго равным нулю. Даль­ше все происходит без изменений; ноль на выходе приводит к тому, что нейрон фактически выпадает из ’ графа вычислений: и прямое вычисление, и обратное рас­пространение градиента • останавливаются на этом нейроне и дальше не идут.

Пример дропаута показан на рис. 4.1, где изображена трехслойная нейронная сеть с пятью входами и тремя слоями по три нейрона. На выходном слое дропа- ут обычно не делают: нам требуется выход определенной размерности, и все его компоненты обычно нужны. А на промежуточных, скрытых слоях дропаут можно применить: на рис. 4.1 видно, как каждый новый тренировочный пример ж* обучает уже немножко другую сеть, где часть соединений выброшена.

Вот и все! Очень простая идея и никакой математики. Основной математиче­ский результат работ [ 129,246] состоит в ответе на вопрос о том, как же потом при­менять обученную сеть. На первый взгляд кажется, что нужно опять сэмплировать кучу «прореженных» сетей, считать их результаты, усреднять... нет, это не будет работать. Но на самом деле большой вычислительной сложности здесь нет: усред­нение будет эквивалентно применению сети, в которой никакие нейроны не вы­брошены, но выход каждого нейрона умножен на вероятность р, с которой нейрон оставляли при обучении. Математическое ожидание выхода нейрона при этом со­хранится, а это именно то, что нужно. Кстати, практика показывает, что для очень широкого спектра архитектур и приложений замечательно подходит р = *, так что эту вероятность можно специально и не подбирать.

И эксперименты в [129, 246], и. вся последующая практика обучения нейрон­ных сетей показывают, что дропаут действительно дает очень серьезные улучше­ния в качестве обученной модели в самых разных приложениях. Мы с вами тоже уже применяли его на практике в разделе 3.6, так что не будем повторяться. Од­нако история еще не закончена, ведь на первый взгляд дропаут выглядит ужасно загадочно: почему вдруг надо выкидывать нейроны? Какой в этом смысл?

Одной из первых попыток объяснить это явление концептуально были рассуж­дения Джеффри Хинтона в исходной статье о дропауте [ 129] и сопутствующих до­кладах. Хинтон полагал, что дропаут — это своеобразный метод добиться огромно­го усреднения моделей. Известно, что это очень полезный на практике трюк; мно­гие Kaggle-соревнования[47] выигрываются при помощи большого ансамбля моде­лей[48]. И Хинтону с соавторами удалось показать, что дропаут эквивалентен усред­нению всех тех моделей, которые получались на каждом шаге случайным выбрасы­ванием отдельных нейронов. Иначе говоря, мы усредняем 2N возможных моделей (где N — число нейронов, которые могут быть выкинуты или оставлены), да не просто разных моделей, а разных архитектур нейронных сетей!

Другая мотивация для дропаута приходит из теории эволюции: методика дро- паута очень похожа на половое размножение. Действительно, на первый взгляд ка­жется, что эволюции нет нужды придумывать разнополых существ: если какие-то гены научатся хорошо «работать вместе», то лучше передать эту хорошую комби­нацию дальше, в то время как половое размножение может нарушить адаптивные сочетания генов.

Однако выясняется, что на самом деле такое разрушение для эволюции скорее полезно: все самые высокоорганизованные животные размножаются именно по­ловым путем, а почкование — удел губок и кишечнополостных. Объяснение этому примерно то же, что и объяснение полезности дропаута: важно не столько собрать хорошую комбинацию генов, сколько собрат ь устойчивую и хорошую комбинацию генов, которая потом будет широко воспроизводиться и сможет стать основой для новой линии потомков. А этого проще достичь, если заставлять гены, как признаки в нейронной сети, «работать» поодиночке, не рассчитывая на соседа (который при половом размножении может просто пропасть)[49].

И наконец, третий возможный взгляд: дропаут очень похож на то, что проис­ходит при связях между живыми нейронами в человеческом мозге. Мы уже гово­рили, что нейроны работают стохастически, то есть посылают сигналы не посто­янно, а в виде случайного процесса, и его интенсивность зависит от того, возбуж­ден нейрон или нет. Взгляды эти, конечно, очень интересные и наверняка верные, но сложно понять, какие из них можно сделать выводы: и так было понятно, что дропаут полезен, и делать его надо. Однако недавно был разработан другой, более математически концептуальный взгляд на дропаут, из которого вытекают новые интересные факты; в частности, он привел к разработке правильного метода того, как делать дропаут в рекуррентных сетях. Сейчас нам, правда, еще рановато о нем говорить; давайте отложим этот разговор до конца книги, до раздела 10.5, а сами пойдем дальше — к инициализации весов.

4.2. Как инициализировать веса

Я хочу стать художником... Что же мне нарисовать? Нарисую петушка! Я их много видел — и живых петушков и нарисован­ных... Вот только с чего начать? С головы или с хвоста? Самое трудное — это начать! Начну с головы, а потом подрисую все ос­тальное: хвост, крылья и лапки со шпорами... Вот! Хороший полу­чился гребешок. Как настоящий! Теперь нарисую глаза и клюв... Что такое? Получился попугай!

С. Михалков. С чего начать?

В этом разделе мы обсудим еще одну проблему, которая оказывается особенно важ­ной для глубоких нейронных сетей. Как мы уже обсуждали, обучение сети — это большая и сложная задача оптимизации в пространстве очень высокой размерно­сти. Решаем мы ее фактически методами локального поиска: сколько ни придумы­вай хитрых способов ускорить градиентный спуск, обойти небольшие локальные минимумы, выбраться из «ущелий», мы все равно не сможем изменить тот факт, что градиентный спуск — это метод местного значения, и ищет он только локаль­ный минимум/максимум. Мы не знаем никаких методов глобальной оптимизации, которые позволили бы найти самый лучший локальный оптимум для такой слож­ной задачи, как обучение глубокой нейронной сети. Поэтому вполне естественно, что один из ключевых вопросов состоит в том, где начинать этот локальный поиск: в зависимости от качества начального приближения можно попасть в самые раз­ные локальные оптимумы. Хорошая инициализация весов может позволить нам обучать глубокие сети и лучше (в смысле метрик качества), и быстрее (в смыс­ле числа требующихся обновлений весов, то есть числа итераций, то есть времени обучения).

Мы уже упоминали первую идею, которая привела к большим успехам в этом направлении: предобучение без учителя (unsupervised pretraining). Можно обучать


отдельные слои глубокой сети без учителя, последовательно, а затем веса полу­ченных слоев считать начальным приближением и дообучать уже на размеченном наборе данных. Как это часто бывает в исследованиях нейронных сетей, эта идея тоже появилась еще во второй половине 1980-х годов: в опубликованной в 1986 го­ду работе [26] строится глубокая архитектура, отдельные части которой обучаются как автокодировщики[50], а затем объединяются в общую модель.

Однако настоящий расцвет предобучения без учителя начался в середине пер­вого десятилетия XXI века. Именно оно обусловило ту самую революцию обуче­ния глубоких сетей, которой вся эта книга обязана своим появлением. Любопытно, что хотя сейчас обучение нейронных сетей можно назвать достаточно простым для изучения инструментом2, и в этой книге мы достаточно быстро объясняем обуче­ние нейронных сетей, начиная от самых азов, в развитии метода без вероятностных моделей и методов приближенного вероятностного вывода не обошлось. Основ­ным инструментом для предобучения без учителя в работах группы Хинтона стали так называемые ограниченные машины Больтщана (restricted Boltzmann machines).

В этой книге мы не будем подробно объяснять, что это такое. Достаточно будет сказать, что это вероятностная модель, также известная с 80-х годов прошлого ве­ка [2,225,499], в которой есть видимые (visible) переменные, значения которых мы знаем, и скрытые. (hidden), значений которых мы не знаем, а также связи между ними. И задача состоит в том, чтобы обучить веса этих связей так, чтобы распреде­ление, порождаемое скрытыми переменными на видимых, было как можно больше похоже на распределение входных данных.

Алгоритм, который такое обучение реализует, получил название contrastive divergence^. Он представляет собой упрощенную версию алгоритма сэмплирова­ния Монте-Карло для соответствующей вероятностной модели. Этот алгоритм то­же придуман Хинтоном, причем еще в 2002 году, до начала революции глубокого обучения [219], а в 2005 году в работе [72] появилась ключевая идея предобучения: начать с contrastive divergence, чтобы обучить начальную точку, а потом дообучить результат при помощи обычного обучения с учителем. Таким же образом мож­но построить и глубокую модель: сначала обучить первый слой как ограниченную


машину Больцмана, затем использовать скрытые вершины первого слоя как види­мый слой второго уровня, потом так же с третьим... а в конце объединить все в одну большую модель с несколькими слоями, использовать веса машин Больцмана как начальное приближение и дообучить результат с учителем.

Такая конструкция получила название глубокой машины Больцмана (Deep Boltzmann machine, DBN) [466]. После своего появления в 2005-2006 годах этот подход к предобучению несколько лет применялся очень активно; он подробно описан в уже ставших классическими публикациях Джеффри Хинтона и его кол­лег и аспирантов, особенно Руслана Салахутдинова [220, 221, 224, 464, 467, 468, 505, 516]. Есть и теоретические результаты, показывающие, что вся эта конструк­ция действительно делает то, что надо, то есть улучшает некоторую оценку общего правдоподобия модели [223].

Можно подойти к этому вопросу и с другой стороны. Ограниченная машина Больцмана обучает веса между видимым и скрытым слоем так, чтобы как можно лучше по скрытому слою восстанавливать видимый... ничего не напоминает? Дей­ствительно, это весьма похоже на ситуацию обучения одного слоя нейронной сети, если еще точнее — на обучение однослойного автокодировщика. И действительно, вскоре появились и аналогичные глубокие конструкции, основанные на автокоди­ровщиках: обучили первый автокодировщик, использовали выделяемые им при­знаки как входы второго и т.д. Этот подход, известный как многоярусные автоко­дировщики (stacked autoencoders), развивался в тот же период в основном в группе Йошуа Бенджи [148, 195], а в контексте сверточных сетей — в группе Яна ЛеКу­на [303].

Почему это работает? Масштабное исследование [567], в 2010 году предприня­тое в группе Бенджи, показало, что предобучение без учителя действительно по­могает практически любой глубокой модели, и выдвинуло интересную гипотезу о том, почему так происходит. Авторы предположили, что предобучение высту­пает в качестве своеобразного метода регуляризации, связанного с общим подхо­дом к вероятностным моделям. Дело в том, что в то время как «обычное» обуче­ние глубокой сети касается только восстановления выхода у по входу ж, то есть пытается обучить условное распределение р(у | ж), порождающая вероятностная модель (такая, как, например, машина Больцмана) обучает совместное распределе­ние р(ху) = р(у | ж)р(ж), то есть старается еще и выразить распределение данных, которые попадаются на входах сети (мы подробнее поговорим о порождающих мо­делях в разделе 8.2). В итоге это приводит к инициализации сети в той области про­странства весов, где веса описывают и условное распределение р(у | ж), и собствен­но распределение данных р( ж), и в результате есть шанс, что обучение с учителем затем сойдется в более хорошо обобщающийся и менее склонный к оверфиттингу локальный оптимум, чем при случайной инициализации[51].

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

1. Предобучение слоев происходит последовательно, от нижних к верхним. Это позволяет избежать проблемы затухающих градиентов и существенно умень­шает объем вычислений на каждом этапе.

2. Предобучение протекает без учителя, то есть без учета имеющихся размечен­ных данных. Это часто позволяет существенно расширить обучающую вы­борку: понятно, что собрать миллионы изображений из Интернета без учета контекста и описания куда проще, чем собрать даже тысячу правильно раз­меченных рукописных цифр, а собрать много сырой человеческой речи куда проще, чем речь с размеченными фонемами.

3. В результате предобучения получается модель, которую затем нужно дообу- чить на размеченных данных. И модели, обученные таким образом, в конеч­ном счете стабильно сходятся к существенно лучшим решениям, чем при слу­чайной инициализации.

...По крайней мере, так было во второй половине 2000-х годов, когда предобу­чение посредством ограниченных машин Больцмана или автокодировщиков было в расцвете. Сейчас его тоже никто не мешает делать, скорее всего, результаты слег­ка улучшатся. Но все-таки предобучение — это достаточно сложная и дорогосто­ящая процедура. Фактически получается, что нужно научиться делать две разных процедуры обучения, настраивать их обе, причем предобучение скорее всего будет более хрупкой и сложной фазой, чем собственно обучение с учителем. Конечно, хотелось бы как-нибудь обойтись без предобучения, так что кроме вопроса о том, почему оно работает хорошо, люди задались и обратным вопросом: почему случай­ная инициализация работает плохо и можно ли что-то сделать для того, чтобы ее улучшить?

Важной вехой на этом пути стала совместная работа Ксавье Глоро (Xavier Glorot) и Йошуа Бенджи [179], вышедшая в 2010 году. Формально поставленный там вопрос был именно «исследовательский»: почему глубокие сети трудно обу­чать сразу целиком? Выяснилось, что результат обучения на практике очень силь­но зависит от первоначальных значений весов. И хотя полноценное предобучение с помощью ограниченных машин Больцмана в современной практике встречается редко, все равно очень важно инициализировать веса правильно. И основным ре­зультатом [179] стал простой и хорошо мотивированный способ инициализации весов, позволяющий существенно ускорить обучение и улучшить качество. В ре­зультате он даже получил название в честь Глоро: его часто называют инициализа­цией Ксавье (Xavier initialization).

с частичным привлечением учителя (semi-supervised learning). Более того, модели, оптимизирующие функцию ошибки, которая комбинирует в себе как ошибку на правильных ответах (supervised), так и часть, отвечающую за восстановление исходных данных (unsupervised), обычно показывают резуль­таты лучше, чем при простом предобучении. Этот подход пока не вошел в мейнстрим, но уж сноски точно заслуживает...

Для того чтобы понять, в чем идея инициализации Ксавье, давайте рассмотрим дисперсию значений активации у слоев нейронной сети. Для начала покажем, как связаны дисперсии последовательных слоев сети. У одного-единственного нейро­на значение активации (то есть выход перед функцией активации) выглядит так:

у = wT® + b = WiXj + 6,

i

где х — вектор входных значений, a w — вектор весов нейрона. Получается, что дисперсия Var(?/) не зависит от свободного члена b и выражается через дисперсии х и w. Для г-го слагаемого суммы Y2i Щ которое мы обозначим как у\ = в предположении о том, что wi и xi независимы (что вполне естественно), мы по­лучим дисперсию:

Var (yi) = Var («дод) = Е [xfwf. - (Е [одю<])2 =

= Е [х{]2 Var (w) + Е [wi] 2 Var (x,) + Var (w{ Var (х{.

Если мы используем симметричные функции активации и случайно инициали­зируем веса со средним значением, равным нулю, то первые два члена последнего выражения оказываются тоже равными нулю, а значит:

Var (y) = Var (w) Var (x).

Если теперь мы предполагаем, что как #2, так и wi инициализируются из одного и того же распределения, причем независимо друг от друга (это сильное предполо­жение, но в данном случае вполне естественное), мы получим:

(

nout \        nout

52 Ш I = 52 Var M = nou tVar (wf Var Х,

i=i /        i=i

где n 0ut — число нейронов последнего слоя. Другими словами, дисперсия выходов пропорциональна дисперсии входов с коэффициентом nou(Var (wi).

До работы [179] стандартным эвристическим способом случайно инициализи­ровать веса новой сети[52] было равномерное распределение следующего вида:


В этом случае получается, что:

 

     
Var (wi) = -2
 
1 \ 2 = 1 V^out / 3n-0ut
 


 

После нескольких слоев такое преобразование параметров распределения зна­чений между слоями сети фактически приводит к затуханию сигнала: дисперсия результата слоя каждый раз уменьшается, фактически делится на 3, а среднее у него было нулевое.

Аналогичная ситуация повторяется и на шаге обратного распространения ошибки при обучении. Например, если                                                                                                             где I — номер слоя, а /

функция активации, то производная функции ошибки L, согласно обычной про­цедуре обратного распространения ошибки, будет такой:

 

дь ду)'" ‘


Если мы используем симметричную функцию активации с единичной произ­водной в окрестности нуля (например, tanh), то                                                                                                      ~ 1, и наблюдается ситуа­

ция, аналогичная вычислению функции, но теперь мы получим коэффициент про­порциональности для дисперсии njnVar (w \), где j — число нейронов во входном слое, а не на выходе.

Идея Глоро и Бенджи заключается в том, что для беспрепятственного рас­пространения значений активации и градиента по сети дисперсия в обоих слу­чаях должна быть примерно равна единице. Поскольку для неодинаковых разме­ров слоев невозможно удовлетворить оба условия одновременно, они предложили инициализировать веса очередного слоя сети симметричным распределением с та­кой дисперсией:

Уаг(у*) =          -  ,

Щп ' ™out

что для равномерной инициализации приводит к следующему распределению:

                           ч/б
ч/^in + nout V^iii^ ^out

Давайте поставим эксперимент и проверим, так ли хороша на самом деле эта нормализованная инициализация. Для этого зададим простую полносвязную мо­дель и будем оценивать точность на тестовом множестве в датасете MNIST. Сна­чала импортируем все необходимое из Keras:

from keras.models import Sequential

from keras.layers import Dense

Как и в TensorFlow, в Keras набор данных MNIST доступен «из коробки»:

from keras.datasets import mrnst

(x_train, y_train), (x_test, y_test) = mnist.load-data()

Однако на этот раз правильные ответы заданы в виде цифр, и нам придется са­мостоятельно перекодировать их в виде векторов. Для этого можно использовать модуль np_utils, входящий в состав Keras:

frcm keras. utils imjx^rt np__utils

Y_trasn = np-titlls.tO-categoorca^y-train, 10)

Y_test = np__utets.to_ccaegoricaa(y_test, 10)

Теперь осталось для удобства перевести матрицы X_trasn и X_test из целочис­ленных значений на отрезке [0,255] к вещественным на [0,1] (нормализовать), а также сделать из квадратных изображений размера 28 х 28 пикселов одномер­ные векторы длины 784; это значит, что сами тензоры X_trasn и X_test будут иметь размерность (число примеров) х 784:

X_trasn = X_train.reshape([-1, 28*28]) / 255.

X_test = X_test.reshape([-1, 28*28]) / 255.

Все, данные готовы. Поскольку мы собираемся определять сразу две одинако­вые модели, различающиеся только способом инициализации весов, давайте сразу объявим соответствующую функцию.

def сгеаte_model(init): model = SequenntatO moodl.add(Dense(100, inpet-shape=(28*28,), init=init, activation='tanh’)) moden.add(Dnnse(100, init=init, activation=’tanh’)) moodL add(Dense(100,. init=init, actsvation^tanh')) moodEadd(Dense(100, init=init, activation=’tanh')) moodkadd(Dense(10, init=init, activation^softmax'))

return model

В этом коде функция create_model принимает на вход текстовый параметр, ко­торый интерпретируется как тип инициализации. Для нашего эксперимента это будут значения uniform и olorot_normal. А возвращает функция простую полносвяз­ную модель с четырьмя промежуточными слоями, каждый размера 100. Везде, кро­ме последнего слоя, мы использум в качестве функции активации гиперболиче­ский тангенс, а в последнем слое — softmax, так как собираемся использовать в ка­честве функции потерь перекрестную энтропию.

Процесс компиляции модели и ее обучения задается очень просто:

uniform-model = сгеаtejnmoeeC"uniform")

eniform-modee.compile(loss=’cateoorscal_crossentropy', optSmizer=’sod', meerics^'accuracy']) eniform_model. fs^t:(x_train, YJtrain,

batch_size=64, nb_epoch=30, verbose=l, validation-data^x-test, Y_test))

Рис. 4.2. Сравнение инициализации Ксавье и случайной инициализации весов

 

glorotjnodel = create_model(Hglorot_nomaV’) glorot-Fiodel. cnnpi1Lo(

l^oss=’catogoricalL_c^i^ossontropy', optim.zore’sgd’, me tries=[’accuracy’]) glorot_modeliftt:(x_travb Y_train,

batch_sizo=64, nb_epoch=30, vorbose=l, valtdation_data=(x_tost, Y_test))

Для того чтобы достаточно «честно» и детально сравнить два способа инициа­лизации, мы обучали каждую из моделей в течение 30 эпох по 10 раз каждую, а за­тем подсчитали среднее значение точности и ее дисперсию после каждой эпохи. Ре­зультат показан на рис. 4.2, где мы изобразили как среднее (собственно кривые), так и дисперсию значений ошибки и точности (затемненная область вокруг кри­вых показывает доверительный интервал в две дисперсии от среднего). Видно, что при инициализации весов по методу Ксавье модель уже после первой эпохи нахо­дит решение с точностью около 90 %, на что модели, чьи веса инициализированы равномерным распределением, требуется около 10 эпох. И при дальнейшем обу­чении «равномерная» модель все время продолжает проигрывать модели с иници­ализацией Ксавье. Более того, и результаты, и улучшение получаются в высшей степени устойчивыми.

Кстати, в работе [179] был сделан и еще один очень интересный и практиче­ски важный вывод. Оказывается, логистический сигмоид а — это весьма неудачная функция активации для глубоких нейронных сетей! Эксперименты Глоро и Бен­джи с глубокими сетями, основанными на логистическом сигмоиде, показали по­ведение, полностью соответствующее тому, о котором мы уже рассуждали в раз­деле 3.5: последний уровень сети очень быстро насыщается, и выбраться из этой ситуации насыщения глубокой сети очень сложно. Почему так?

Хотя доказать строгое утверждение о том, что здесь происходит, доволь­но сложно, есть правдоподобное объяснение, которое как раз различает ло­гистический сигмоид и другие симметричные функции активации, например


Очевидно, что инициализация весов для этой функции активации должна от­личаться. В 2015 году Каймин Хе (Kaiming Не) с соавторами опубликовали рабо­ту [114], в которой, помимо нескольких перспективных модификаций ReLU, пред­ложена и подходящая для этой функции активации схема инициализации.

Поскольку функция активации в этом случае несимметрична, в выражении

Var (wi%i) = Е [a;]2 Var (w) + Е [w*]2 Var (x) + Var (wi) Var (x{)

можно сразу обнулить только второй член. И тогда мы получили:

Var (wiXi) = Е [ xi ]2 Var (wi) 4- Var (w$) Var (x) = Var (w) E Xj,

то есть

Var = njVar (гЛ) E

где l обозначает номер текущего уровня, а п® число нейронов на уровне I.

Пусть теперь х^= max(0,?/*-1)), а                    распределен симметрично относи­

тельно нуля. Тогда:

E [(*w) 2 = 5 var                       '

а значит,

(0

Var         = -y-Var              Var             .

Теперь это очевидным образом приводит к выводу о том, какой должна быть дисперсия инициализации весов для ReLU. Наш окончательный вывод о диспер­сии отличается от инициализации Ксавье только тем, что теперь нет никакого n()ut‘ если приравнять фактор изменения дисперсии единице, мы получим:

Var         =1 и Var(wi) =                  .

™in

Любопытно, что в [114] для ReLU использовалось не равномерное, а нормаль­ное распределение вокруг нуля с соответствующей дисперсией; такой способ ини­циализации часто используется на практике в глубоких сетях из ReLU-нейронов:

 

Кроме того, в обеих работах свободные члены b предлагается инициализиро­вать нулями: они и сами смогут без проблем обучиться практически при любом алгоритме оптимизации.

гиперболический • тангенс tanh. Рассмотрим последний слой сети, который выгля­дит как f(W+~) где h — выходы предыдущего слоя, Ь — свободные члены послед­него уровня, а / — функция активации последнего уровня, обычно softmax. Когда мы начинаем оптимизировать сложную функцию потерь по параметрам нейрон­ной сети и оцениваем качество как среднюю ошибку на тестовом множестве, пона­чалу выходы h фактически не несут никакой полезной информации о входах, ведь первые уровни еще совсем не обучены.

В такой ситуации оказывается, что неплохим приближением к оптимальному результату может служить константная функция, выдающая средние значения вы­ходов. Это значит, что значение активации выходного слоя сети f(Wh + Ь) будет обучаться так: сеть подберет подходящие свободные члены Ь и постарается обну­лить слагаемое Wh, которое на ранних этапах обучения выступает в роли скорее шума, чем полезного сигнала.

Иначе говоря, в процессе обучения мы постараемся привести выходы предыду­щего слоя к нулю. И тут-то и проявляется разница: функция а(х) = 1-^_а; имеет область значений (0,1) при среднем значении \, и если мы попытаемся приблизить ее значение к нулю, производная тоже устремится к нулю. Это значит, что если мы обнулим значение логистического сигмоида, мы попадем в область его насыщения, и все станет плохо. А у tanh или, скажем, SoftSign с этим проблем нет: приближая значение к нулю, мы как раз попадаем в окрестность точки х = 0, где производная максимальна, и из нее легко потом сдвинуться в любую нужную сторону. Таким образом, логистический сигмоид самой своей формой мешает обучать глубокую сеть, причем дело может быть буквально в конкретной параметризации: даже если просто заменить а(х) на функцию 2а(х) -1, которая будет иметь область значений от -1 до 1 и максимум производной в нуле, эти проблемы могут исчезнуть.

К сожалению, простой заменой одной функции активации на другую пробле­ма обучения глубоких нейронных сетей не решается. Симметричные функции ак­тивации тоже страдают от целого ряда проблем. Так, например, последовательные слои с нелинейностью вида tanh поочередно насыщаются: значения нейронов слой за слоем сходятся к 1 или —1, что, как и в случае с обнулением аргумента функции сг, выводит оптимизацию на градиентное плато и часто приводит к «плохому» ло­кальному минимуму. Однако, с другой стороны, такое насыщение куда менее веро­ятно и после предобучения посредством ограниченных машин Больцмана, и про­сто после «правильной» случайной инициализации весов.

Все, победа, идеальный и универсальный метод инициализации найден? Не со­всем. Хотя мы действительно получили отличный способ инициализации для ве­сов таких нейронов, как выше, на этом наша история про инициализацию весов не заканчивается. Дело в том, что все вышесказанное относится исключительно к симметричным функциям активации! Это значит, что инициализация Ксавье бу­дет прекрасно работать для логистического сигмоида или гиперболического тан­генса, но в современных сверточных (и не только) архитектурах повсеместно ис­пользуются и несимметричные функции активации, особенно часто — ReLU.


В качестве вишенки на торте добавим, что авторы работы [114] заметили нюанс, ускользнувший от Глоро и Бенджи, которые пытались найти баланс между диспер­сиями прямого и обратного шагов. Предположим, что для инициализации весов сети мы выбрали формулы инициализации Ксавье, но ограничение взяли только из шага обратного распространения ошибки, то есть

n^Var(wi) = 1, или Var(wj) =

nin

Тогда, судя по тому, что мы обсуждали выше, дисперсия при прямом шаге вы­числения должна будет или «затухать», или «взрываться» пропорционально отно- ( /), (0

шению

Но ведь в глубокой сети выходы одного слоя подаются на вход следующему, то есть = п>п '! А это значит, что когда мы возьмем произведение по всем слоям сети, окажется, что все члены посередине сокращаются, и фактор изменения дисперсии становится равным где пОи[ — число выходов последнего слоя сети, а п>п' — число входов первого слоя.

 

Понятно, что каким бы ни было это соотношение, оно уже не является экспо­ненциальной функцией от числа слоев сети и не приводит к затуханию или чрез­м


Поделиться с друзьями:

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...

Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.113 с.