Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...
Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...
Топ:
Проблема типологии научных революций: Глобальные научные революции и типы научной рациональности...
Эволюция кровеносной системы позвоночных животных: Биологическая эволюция – необратимый процесс исторического развития живой природы...
Теоретическая значимость работы: Описание теоретической значимости (ценности) результатов исследования должно присутствовать во введении...
Интересное:
Инженерная защита территорий, зданий и сооружений от опасных геологических процессов: Изучение оползневых явлений, оценка устойчивости склонов и проектирование противооползневых сооружений — актуальнейшие задачи, стоящие перед отечественными...
Принципы управления денежными потоками: одним из методов контроля за состоянием денежной наличности является...
Наиболее распространенные виды рака: Раковая опухоль — это самостоятельное новообразование, которое может возникнуть и от повышенного давления...
Дисциплины:
2020-04-03 | 194 |
5.00
из
|
Заказать работу |
|
|
____________________ 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] было равномерное распределение следующего вида:
В этом случае получается, что:
|
|
После нескольких слоев такое преобразование параметров распределения значений между слоями сети фактически приводит к затуханию сигнала: дисперсия результата слоя каждый раз уменьшается, фактически делится на 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
шению
Но ведь в глубокой сети выходы одного слоя подаются на вход следующему, то есть = п>п '! А это значит, что когда мы возьмем произведение по всем слоям сети, окажется, что все члены посередине сокращаются, и фактор изменения дисперсии становится равным где пОи[ — число выходов последнего слоя сети, а п>п' — число входов первого слоя.
Понятно, что каким бы ни было это соотношение, оно уже не является экспоненциальной функцией от числа слоев сети и не приводит к затуханию или чрезм
|
|
Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...
Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...
Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначенные для поддерживания проводов на необходимой высоте над землей, водой...
Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!