Нейросети и глубокое обучение, глава 3, ч.1: улучшение способа обучения нейросетей |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2019-07-08 11:25 Когда человек учится играть в гольф, большую часть времени он обычно проводит за постановкой базового удара. К другим ударам он подходит потом, постепенно, изучая те или иные хитрости, основываясь на базовом ударе и развивая его. Сходным образом мы пока что фокусировались на понимании алгоритма обратного распространения. Это наш «базовый удар», основа для обучения для большей части работы с нейросетями (НС). В этой главе я расскажу о наборе техник, которые можно использовать для улучшения нашей простейшей реализации обратного распространения, и улучшить способ обучения НС. Среди техник, которым мы научимся в этой главе: лучший вариант на роль функции стоимости, а именно функция стоимости с перекрёстной энтропией; четыре т.н. метода регуляризации (регуляризации L1 и L2, исключение нейронов [dropout], искусственное расширение обучающих данных), улучшающих обобщаемость наших НС за пределы обучающих данных; лучший метод инициализации весов сети; набор эвристических методов, помогающих выбирать хорошие гиперпараметры для сети. Я также рассмотрю и несколько других техник, чуть более поверхностно. Эти обсуждения по большей части не зависят друг от друга, поэтому их можно по желанию перепрыгивать. Мы также реализуем множество технологий в рабочем коде и используем их для улучшения результатов, полученных для задачи классификации рукописных цифр, изученной в главе 1.
Конечно, мы рассматриваем лишь малую толику огромного количества техник, разработанных для использования с нейросетями. Суть в том, что лучший способ войти в мир изобилия доступных техник – это подробное изучение нескольких самых важных из них. Овладение этими важными техниками не только полезно само по себе, оно ещё углубит ваше понимание того, какие проблемы могут возникать при использовании нейросетей. В итоге вы будете подготовлены для быстрой адаптации новых техник по необходимости. Функция стоимости с перекрёстной энтропией Большинству из нас неприятно быть неправым. Вскоре после начала обучения игре на пианино я дал небольшой концерт перед аудиторией. Я нервничал, и начал играть произведение на октаву ниже, чем надо. Я запутался, и не мог продолжать, пока кто-то не указал мне на ошибку. Мне было очень стыдно. Однако, хотя это и неприятно, мы также очень быстро обучаемся, решив, что мы ошиблись. И уж точно в следующий раз, когда я выступал перед аудиторией, я играл в нужной октаве! И наоборот, мы обучаемся медленнее, когда наши ошибки определены не очень хорошо.
где a – выход нейрона, когда на входе используется x=1, и y=0 – желаемый выход. Чтобы записать это непосредственно через вес и смещение, вспомним, что a=?(z), где z=wx+b. Используя цепное правило для дифференцирования по весу и смещению, получаем:
где я подставил x=1 и y=0. Чтобы понять поведение этих выражений, давайте подробнее взглянем на член ?'(z) справа. Вспомним форму сигмоиды: Из графика видно, что когда выход нейрона близок к 1, кривая становится очень плоской, и ?'(z) становится маленькой. Уравнения (55) и (56) говорят нам о том, что ?C/?w и ?C/?b становятся очень маленькими. Отсюда и растёт замедление обучения. Более того, как мы увидим чуть позже, замедление обучения происходит, по сути, по той же причине и в НС более общего характера, а не только в нашем простейшем примере.Представляем функцию стоимости с перекрёстной энтропией Как нам быть с замедлением обучения? Оказывается, мы можем решить проблему, заменив квадратичную функцию стоимости другой функцией стоимости, известной под названием перекрёстной энтропии. Чтобы понять перекрёстную энтропию, отойдём от нашей простейшей модели. Допустим, мы обучаем нейрон с несколькими входными значениями x1,x2,… соответствующими весами w1,w2,… и смещением b:
где n – общее количество единиц обучающих данных, сумма идёт по всем обучающим данным x, а y – соответствующий желаемый выход.
Приводя к общему знаменателю и упростив, получим:
Используя определение сигмоиды, ?(z)=1/(1+e?z) и немножко алгебры, можно показать, что ??(z) = ?(z)(1 ? ?(z)). Проверить это я попрошу вас в упражнении далее, но пока что примем это, как истину. Члены ??(z) и ?(z)(1??(z)) сокращаются, и это приводит к
Прекрасное выражение. Из него следует, что скорость, с которой обучаются веса, контролируется ?(z)?y, то есть, ошибкой на выходе. Чем больше ошибка, тем быстрее обучается нейрон. Этого можно было интуитивно ожидать. Этот вариант избегает замедления обучения, вызванного членом ?’(z) в аналогичном уравнении для квадратичной стоимости (55). Когда мы используем перекрёстную энтропию, член ?’(z) сокращается, и нам уже не приходится волноваться о его малости. Это сокращение – особое чудо, гарантируемое функцией стоимости с перекрёстной энтропией. На самом деле, конечно, это не совсем чудо. Как мы увидим позднее, перекрёстную энтропию специально выбрали именно за это свойство.
Это опять-таки помогает избежать замедления обучения из-за члена ?’(z) в аналогичном у равнении для квадратичной стоимости (56). Упражнение
Вернёмся к нашему надуманному примеру, с которым мы игрались ранее, и посмотрим, что случится, если вместо квадратичной стоимости мы будем использовать перекрёстную энтропию. Чтобы настроиться, мы начнём со случая, в котором квадратичная стоимость отлично сработала, когда начальный вес был 0,6 а смещение – 0,9. В оригинале статьи есть интерактивная форма, в которой можно нажать кнопку «Run» и посмотреть, что происходит при замене квадратичной стоимости на перекрёстную энтропию. Ничего удивительного, нейрон в данном случае обучается прекрасно, как и ранее. Теперь посмотрим на случай, в котором раньше нейрон застревал, с весом и смещением, начинающимися с величины 2,0. Успех! На этот раз нейрон обучился быстро, как мы и хотели. Если наблюдать пристально, можно увидеть, что наклон кривой стоимости изначально более крутой, по сравнению с плоским регионом соответствующей кривой квадратичной стоимости. Эту крутость даёт нам перекрёстная энтропия, и не даёт застрять там, где мы ожидаем наискорейшее обучение нейрона, когда он начинает с очень больших ошибок. Я не сказал, какая скорость обучения использовалась в последних примерах. Ранее с квадратичной стоимостью мы использовали ?=0,15. Должны ли мы использовать такую же скорость и в новых примерах? На самом деле, меняя функцию стоимости, нельзя точно сказать, что значит – использовать «такую же» скорость обучения; это будет сравнения яблок с апельсинами. Для обеих функций стоимости я экспериментировал, подыскивая скорость обучения, позволяющую увидеть происходящее. Если вам всё же интересно, то в последних примерах ?=0,005. Вы можете возразить, что изменение скорости обучения лишает графики смысла. Кому какая разница, как быстро обучается нейрон, если мы могли произвольно выбирать скорость обучения? Но это возражение не учитывает главного. Смысл графиков не в абсолютной скорости обучения, а в том, как меняется эта скорость. При использовании квадратичной функции обучение идёт медленнее, если нейрон сильно ошибается, а потом идёт быстрее, когда нейрон подходит к нужному ответу. С перекрёстной энтропией обучение идёт быстрее, когда нейрон сильно ошибается. И эти утверждения не зависят от заданной скорости обучения. Мы исследовали перекрёстную энтропию для одного нейрона. Однако это легко обобщить на сети со многими слоями и многими нейронами. Допустим, что y=y1, y2,… — желаемые значения выходных нейронов, то есть, нейронов в последнем слое, а aL1, aL2,… — сами выходные значения. Тогда перекрёстную энтропию можно определить, как:
Это то же самое, что уравнение (57), только теперь наша ?j суммирует по всем выходным нейронам. Не буду подробно разбирать производную, однако разумно предположить, что с использованием выражения (63) мы можем избежать замедления в сетях с многими нейронами. Если интересно, вы можете взять производную в задаче ниже. Упражнения
Задачи
Использование перекрёстной энтропии для классификации цифр из MNIST Перекрёстную энтропию легко реализовать в виде части программы, обучающей сеть при помощи градиентного спуска и обратного распространения. Позже мы сделаем это, разработав улучшенную версию нашей ранней программы классификации рукописных цифр из MNIST, network.py. Новая программа называется network2.py, и включает не только перекрёстную энтропию, но и несколько других техник, разработанных в этой главе. А пока посмотрим, насколько хорошо наша новая программа классифицирует цифры MNIST. Как и в главе 1, мы будем использовать сеть с 30 скрытыми нейронами, и мини-пакетом размером в 10. Установим скорость обучения ?=0,5 и будем обучаться 30 эпох. Как я уже говорил, нельзя точно сказать, какая скорость обучения подойдёт в каком случае, поэтому я экспериментировал с подбором. Правда, существует способ очень грубо эвристически связать скорость обучения с перекрёстной энтропией и квадратичной стоимостью. Раньше мы видели, что в членах градиента для квадратичной стоимости есть дополнительный член ?'=?(1-?). Допустим, мы усредним эти значения для ?, ?10d? ? (1??)=1/6. Видно, что (очень грубо) квадратичная стоимость в среднем обучается в 6 раз медленнее для той же скорости обучения. Это говорит о том, что хорошей отправной точкой будет поделить скорость обучения для квадратичной функции на 6. Конечно, это совершенно не строгий аргумент, и не стоит принимать его слишком серьёзно. Но он иногда может быть полезным в качестве отправной точки.
Отметьте, кстати, что команда net.large_weight_initializer() используется для инициализации весов и смещений так же, как описано в главе 1. Нам нужно прогнать её, потому что позже мы изменим инициализацию весов по умолчанию. В итоге, после запуска всех указанных выше команд, мы получим сеть, работающую с точностью в 95,49%. Это очень близко к результату из первой главы, 95.42%, использовавшему квадратичную стоимость. Давайте также посмотрим на случай, где мы используем 100 скрытых нейронов и перекрёстную энтропию, а всё остальное оставляем таким же. В этом случае точность получается 96,82%. Это серьёзное улучшение по сравнению с результатами из первой главы, где мы достигли точности в 96.59%, используя квадратичную стоимость. Изменение может показаться небольшим, но подумайте о том, что ошибка упала с 3,41% до 3,18%. То есть, мы устранили примерно 1/14 ошибок. Это довольно неплохо. Довольно приятно, что функция стоимости с перекрёстной энтропией даёт нам сходные или лучшие результаты по сравнению с квадратичной стоимостью. Однако они не доказывают однозначно, что перекрёстная энтропия – лучший выбор. Дело в том, что я вовсе не старался выбирать гиперпараметры – скорость обучения, размер мини-пакета, и т.д. Чтобы улучшение получилось более убедительным, нам нужно как следует заняться их оптимизацией. Но результаты всё равно вдохновляющие, и подтверждают наши теоретические выкладки о том, что перекрёстная энтропия – лучший выбор, чем квадратичная функция стоимости. В этом ключе пройдёт вся эта глава и, в принципе, остаток книги. Мы будем вырабатывать новую технику, испытывать её, и получать «улучшенные результаты». Конечно, хорошо, что мы видим эти улучшения. Но интерпретировать их всегда сложно. Убедительно будет только, если мы увидим улучшения после серьёзной работы по оптимизации всех остальных гиперпараметров. А это довольно сложная работа, требующая больших вычислительных ресурсов, и обычно мы не будем заниматься таким тщательным расследованием. Вместо этого мы будем идти дальше на базе неформальных тестов, как тех, что приведены выше. Но вам нужно иметь в виду, что такие тесты не являются однозначным доказательством, и внимательно следить за теми случаями, когда аргументы начинают сбоить. Пока что мы подробно обсуждали перекрёстную энтропию. Зачем тратить столько сил, если она даёт такое небольшое улучшение наших результатов по MNIST? Позже в этой главе мы увидим другие техники – в частности, регуляризацию – дающие куда как более сильные улучшения. Так зачем мы концентрируемся на перекрёстной энтропии? В частности потому, что перекрёстная энтропия – это часто используемая функция стоимости, поэтому в ней стоит хорошо разобраться. Но более важной причиной будет то, что насыщение нейронов – важная в области нейросетей проблема, к которой мы будем постоянно возвращаться на протяжении книги. Поэтому я так подробно обсуждал перекрёстную энтропию, поскольку это хорошая лаборатория для того, чтобы начать разбираться в насыщении нейронов и в том, как можно искать подходы к этой проблеме. Что означает перекрёстная энтропия? Откуда она берётся? Наше обсуждение перекрёстной энтропии вращалось вокруг алгебраического анализа и практической реализации. Это полезно, но в итоге остаются без ответа более широкие концептуальные вопросы, например: что означает перекрёстная энтропия? Есть ли интуитивный способ её представлять? Как люди вообще могли придумать перекрёстную энтропию?
Если бы мы выбрали функцию стоимости, делающую их истинными, то они бы довольно просто описали бы интуитивное понимание того, что чем больше изначальная ошибка, тем быстрее обучается нейрон. Они бы также устранили проблему с замедлением обучения. На самом деле, начав с этих уравнений, мы бы показали, что возможно вывести форму перекрёстной энтропии, просто следуя математическому чутью. Чтобы увидеть это, отметим, что, исходя из цепного правила, мы получаем:
Используя в последнем уравнении ??(z) = ?(z)(1??(z)) = a(1?a), получим:
Сравнив с уравнением (72), получим:
Интегрируя это выражение по a, получим:
Это вклад отдельного обучающего примера x в функцию стоимости. Чтобы получить полную функцию стоимости, нам нужно усреднить по всем обучающим примерам, и мы приходим к:
Константа тут – средняя по отдельным константам каждого из обучающих примеров. Как видим, уравнения (71) и (72) уникальным образом определяют форму перекрёстной энтропии, плоть до общей константы. Перекрёстную энтропию не доставали волшебным образом из воздуха. Её можно было найти простым и естественным образом. Задача
Softmax (функция мягкого максимума) В данной главе мы по большей части будем использовать функцию стоимости с перекрёстной энтропией для решения проблем замедления обучения. Однако мне хочется кратко обсудить ещё один подход к этой проблеме, основанный на т.н. softmax-слоях нейронов. Мы не будем использовать Softmax-слои в оставшейся части главы, поэтому, если вы очень торопитесь, можете пропустить этот раздел. Однако в Softmax всё же стоит разобраться, в частности, потому, что она интересна сама по себе, и в частности потому, что мы будем использовать Softmax-слои в главе 6, в нашем обсуждении глубоких нейросетей.
где в знаменателе мы суммируем по всем выходным нейронам.
В итоге, с увеличением aL4 остальные выходные активации обязаны уменьшаться на то же значение в сумме, чтобы гарантировать, что сумма всех выходных активаций будет равной 1. И, конечно, сходные утверждения будут верны для всех остальных активаций. Упражнение
Мы начинаем немного разбираться в Softmax-функции и том, как ведут себя Softmax-слои. Просто чтобы подвести промежуточный итог: экспоненты в уравнении (78) гарантируют, что все выходные активации будут положительными. Сумма в знаменателе уравнения (78) гарантирует, что выход Softmax в сумме даст 1. Поэтому этот вид уравнения уже не кажется загадочным: это естественный способ гарантировать, чтобы выходные активации формировали распределение вероятности. Softmax можно представить себе, как способ изменения масштаба zLj с последующим сжатием их в кучку для формирования распределения вероятности. Упражнения
Задача
Проблема замедления обучения Мы уже достаточно близко познакомились с Softmax-слоями нейронов. Но пока что мы не видели, как Softmax-слои позволяют нам решить проблему замедления обучения. Чтобы понять это, давайте определим функцию стоимости на основе «логарифм-правдоподобия». Мы будем использовать x для обозначения обучающего входа сети, и y для соответствующего желаемого выхода. Тогда ЛПС, связанная с этим обучающим входом, будет:
Так что, если мы, к примеру, обучаемся на изображениях MNIST, и на вход пошло изображение 7, тогда ЛПС будет равной ?ln aL7. Чтобы понять это интуитивно, рассмотрим случай, когда сеть хорошо справляется с распознаванием, то есть, уверена, что на входе 7. В этом случае она оценит значение соответствующей вероятности aL7 как близкое к 1, поэтому стоимость ?ln aL7 будет малой. И наоборот, если сеть работает плохо, то вероятность aL7 будет меньше, а стоимость ?ln aL7 будет больше. Поэтому ЛПС ведёт себя так, как можно ожидать от функции стоимости.
Я тут немного поиграл с обозначениями, и использую «y» немного не так, как в прошлом параграфе. Там y обозначало желаемый выход сети – то есть, если на выходе «7», то на входе было изображение 7. А в этих уравнениях y обозначает вектор выходных активаций, соответствующий 7, то есть вектор, у которого все нули, кроме единички в 7-й позиции. Задачи
Переобучение и регуляризация У нобелевского лауреата Энрико Ферми как-то спросили мнение по поводу математической модели, предложенной несколькими коллегами для решения важной нерешённой физической проблемы. Модель прекрасно соответствовала эксперименту, но Ферми отнёсся к ней скептически. Он спросил, сколько свободных параметров в ней можно менять. «Четыре», — сказали ему. Ферми ответил: «Помню, как мой друг Джонни фон Нейман любил говорить, что с четырьмя параметрами туда можно запихнуть и слона, а с пятью можно заставить его махать хоботом».
Используя результаты, мы можем построить график изменения стоимости при обучении сети (графики сделаны при помощи программы overfitting.py): Выглядит обнадёживающе, идёт гладкое уменьшение стоимости, как и ожидалось. Учтите, что я показал только эпохи с 200 по 399. В итоге мы видим в увеличенном масштаба поздние этапы обучения, на которых, как мы увидим далее, и происходит всё самое интересное. Теперь посмотрим, как меняется точность классификации на проверочных данных во времени: Тут я снова увеличил график. В первые 200 эпох, которых тут не видно, точность растёт почти до 82%. Затем обучение постепенно замедляется. Наконец, примерно на 280-й эпохе точность классификации перестаёт улучшаться. На поздних эпохах наблюдаются лишь небольшие стохастические флуктуации вокруг значения точности, достигнутого на 280-й эпохе. Сравните это с предыдущим графиком, где стоимость, связанная с обучающими данными, плавно уменьшается. Если изучать только эту стоимость, то будет казаться, что модель улучшается. Однако результаты работы с проверочными данными говорят нам, что это улучшение – лишь иллюзия. Как и в модели, которая не понравилась Ферми, то, что наша сеть изучает после 280-й эпохи, уже не обобщается на проверочных данных. Поэтому это обучение перестаёт быть полезным. Мы говорим, что после 280-й эпохи сеть переобучается, или переподгоняется [overfitting or overtraining]. Вы можете задуматься над тем, не является ли проблемой то, что я изучаю стоимость на основе обучающих данных, а не точности классификации проверочных данных. Иначе говоря, возможно, проблема в том, что мы сравниваем яблоки с апельсинами. Что будет, если мы сравним стоимость обучающих данных со стоимостью проверочных, то есть, будем сравнивать сравнимые меры? Или, возможно, мы могли бы сравнить точность классификации как обучающих, так и проверочных данных? На самом деле, то же явление проявляется вне зависимости от того, как проводить сравнение. Но изменяются детали. К примеру, давайте посмотрим стоимость проверочных данных: Видно, что стоимость проверочных данных улучшается примерно до 15-й эпохи, а потом вообще начинает ухудшаться, хотя стоимость обучающих данных продолжает улучшаться. Это ещё один признак переобученной модели. Однако встаёт вопрос, какую эпоху мы должны считать точкой, в которой переобучение начинает преобладать над обучением – 15 или 280? С практической точки зрения нас всё же интересует улучшение точности классификации проверочных данных, а стоимость – это всего лишь посредник точности классификации. Поэтому имеет смысл считать эпоху 280 точкой, после которой переобучение начинает преобладать над обучением нашей НС. Ещё один признак переобучения можно увидеть в точности классификации обучающих данных: Точность растёт, доходя до 100%. То есть, наша сеть правильно классифицирует все 1000 обучающих изображений! Тем временем, проверочная точность вырастает лишь до 82,27%. То есть, наша сеть лишь изучает особенности обучающего набора, а не учится распознавать цифры вообще. Похоже на то, что сеть просто запоминает обучающий набор, недостаточно хорошо поняв цифры для того, чтобы обобщить это на проверочный набор. Переобучение – серьёзная проблема НС. Особенно это верно для современных НС, в которых обычно есть огромное количество весов и смещений. Для эффективного обучения нам нужен способ определять, когда возникает переобучение, чтобы не переобучать. А ещё нам хотелось бы уметь уменьшать эффекты переобучения. Очевидный способ обнаружить переобучение – использовать подход выше, следить за точностью работы с проверочными данными в процессе обучения сети. Если мы увидим, что точность на проверочных данных уже не улучшается, надо прекращать обучение. Конечно, строго говоря, это не обязательно будет признаком переобучения. Возможно, точность работы с проверочными и с обучающими данными прекратят улучшаться одновременно. И всё же применение такой стратегии предотвратит переобучение. А мы будем использовать небольшую вариацию этой стратегии. Вспомним, что когда мы загружаем в MNIST данные, мы делим их на три набора:
Пока что мы использовали training_data и test_data, и игнорировали validation_data [подтверждающие]. В validation_data содержится 10 000 изображений, отличающихся как от 50 000 изображений обучающего набора MNIST, так и от 10 000 изображений проверочного набора. Вместо использования test_data для предотвращения переобучения мы будем использовать validation_data. Для этого мы будем использовать практически ту же стратегию, что была описана выше для test_data. То есть, мы будем вычислять точность классификации validation_data в конце каждой эпохи. Как только точность классификации validation_data насытится, мы перестанем обучаться. Эта стратегия называется ранней остановкой. Конечно, на практике мы не сможем сразу же узнать, что точность насытилась. Вместо этого мы будем продолжать обучение, пока не удостоверимся в этом (причём решить, когда нужно остановиться, не всегда просто, и можно использовать для этого более или менее агрессивные подходы). Зачем использовать validation_data для предотвращения переобучения, а не test_data? Это часть более общей стратегии – использовать validation_data для оценки разных вариантов выбора гиперпараметров – количества эпох для обучения, скорости обучения, наилучшей архитектуры сети, и т.д. Эти оценки мы используем, чтобы найти и присвоить хорошие значения гиперпараметрам. И хотя я пока ещё этого не упоминал, частично благодаря этому я и сделал выбор гиперпараметров в ранних примерах в книге. Конечно, это замечание не отвечает на вопрос о том, почему мы используем validation_data, а не test_data, для предотвращения переобучения. Оно просто заменяет ответ на более общий вопрос – почему мы используем validation_data, а не test_data, для выбора гиперпараметров? Чтобы понять это, учтите, что при выборе гиперпараметров нам, скорее всего, придётся выбирать из множества их вариантов. Если мы будем назначать гиперпараметры на основе оценок из test_data, мы, возможно, слишком сильно подгоним эти данные именно под test_data. То есть, мы, возможно, найдём гиперпараметры, хорошо подходящие под особенности конкретных данных из test_data, однако работа нашей сети не будет обобщаться на другие наборы данных. Этого мы избегаем, подбирая гиперпараметры при помощи validation_data. А потом, получив нужные нам ГП, мы проводим итоговую оценку точности с использованием test_data. Это даёт нам уверенность в том, что наши результаты работы с test_data являются истинной мерой степени генерализации НС. Иначе говоря, подтверждающие данные – это такие особые обучающие данные, помогающие нам обучиться хорошим ГП. Такой подход к поиску ГП иногда называют методом удержания, поскольку validation_data «удерживают» отдельно от training_data. На практике, даже после оценки качества работы на test_data мы захотим поменять наше мнение и попробовать другой подход – возможно, другую архитектуру сети – который будет включать поиски нового набора ГП. В этом случае не возникнет ли опасность того, что мы излишне приспособимся к test_data? Не потребуется ли нам потенциально бесконечное количество наборов данных, чтобы мы были уверены в том, что наши результаты хорошо обобщаются? В целом это глубокая и сложная проблема. Но для наших практических целей мы не будем слишком сильно переживать по этому поводу. Мы просто нырнём с головой в дальнейшие исследования, используя простой метод удержания на основе training_data, validation_data и test_data, как описано выше. Пока что мы рассматривали переобучение с использованием 1000 обучающих изображений. Что будет, если мы используем полный обучающий набор из 50 000 изображений? Все остальные параметры мы оставим без изменений (30 скрытых нейронов, скорость обучения 0,5, размер мини-пакета 10), но будем обучаться 30 эпох с использованием всех 50 000 картинок. Вот график, на котором показана точность классификации на обучающих данных и проверочных данных. Отметьте, что здесь я использовал проверочные [test], а не подтверждающие [validation] данные, чтобы результаты было проще сравнивать с более ранними графиками. Видно, что показатели точности на проверочных и обучающих данных остаются ближе друг к другу, чем при использовании 1000 обучающих примеров. В частности, наилучшая точность классификации, 97,86%, всего на 2,53% выше, чем 95,33% проверочных данных. Сравните с ранним разрывом в 17,73%! Переобучение происходит, но сильно уменьшилось. Наша сеть гораздо лучше обобщает информацию, переходя с обучающих на проверочные данные. В целом, один из лучших способов уменьшения переобучения — увеличение объёма обучающих данных. Взяв достаточно обучающих данных, сложно переобучить даже очень крупную сеть. К сожалению, получить обучающие данные бывает дорого и/или сложно, поэтому такой вариант не всегда оказывается практичным. Регуляризация Увеличение количества обучающих данных – один из способов уменьшения переобучения. Есть ли другие способы уменьшения проявлений переобучения? Один из возможных подходов – уменьшение размера сети. Правда, у больших сетей возможностей потенциально больше чем у малых, поэтому к такому варианту мы прибегаем неохотно.
Первый член – обычное выражение для перекрёстной энтропии. Но мы добавили второй, а именно, сумму квадратов всех весов сети. Он масштабируется множителем ?/2n, где ?>0 – это параметр регуляризации, а n, как обычно – размер обучающего набора. Мы обсудим, как выбрать ?. Также стоит отметить, что в член регуляризации не входят смещения. Об этом ниже.
В обоих случаях можно записать регуляризированную функцию стоимости, как
где C0 — оригинальная функция стоимости без регуляризации.
Члены ?C0/?w и ?C0/?w можно вычислить через ОР, как описано в предыдущей главе. Мы видим, что подсчитать градиент регуляризованной функции стоимости легко: просто нужно, как обычно, использовать ОР, а потом добавить ?/n w к частной производной всех весовых членов. Частные производные по смещениям не меняются, поэтому правило обучения градиентным спуском для смещений не отличается от обычного:
Правило обучения для весов превращается в:
Всё то же самое, что и в обычном правиле градиентного спуска, кроме того, что мы сначала масштабируем вес w на множитель 1 — ??/n. Это масштабирование иногда называют ослаблением весов, поскольку оно уменьшает веса. На первый вщгляд кажется, что веса неудержимо стремятся к нулю. Но это не так, поскольку другой член может привести к увеличению весов, если это приводит к уменьшению нерегуляризованной функции стоимости.
где сумма идёт по обучающим примерам x в мини-пакете, а Cx — нерегуляризованная стоимость для каждого обучающего примера. Всё то же самое, что и в обычно правиле стохастического градиентного спуска, за исключением 1 — ??/n, фактора ослабления веса. Наконец, для полноты картины, позвольте записать регуляризованное правило для смещений. Оно, естественно, точно такое же, как и в нерегуляризованном случае (см. уравнение (21)):
где сумма идёт по обучающим примерам x в мини-пакете.
Стоимость обучающих данных постоянно уменьшается, как и раннем случае, без регуляризации: Но на этот раз точность на test_data продолжает увеличиваться в течение всех 400 эпох: Очевидно, регуляризация подавила переобучение. Более того, точность значительно возросла, и пиковая точность классификации достигает 87,1%, по сравнению с пиком 82,27%, достигнутым в случае без регуляризации. И вообще, мы почти наверняка достигаем лучших результатов, продолжая обучение после 400 эпох. Судя по всему, эмпирически, регуляризация заставляет нашу сеть лучше обобщать знания, и значительно уменьшает эффекты переобучения. Что произойдёт, если мы оставим наше искусственное окружение, в котором используется всего 1 000 обучающих картинок, и вернёмся к полному набору из 50 000 изображений? Конечно, мы уже увидели, что переобучение представляет куда как меньшую проблему с полным набором из 50 000 изображений. Помогает ли улучшить результат регуляризация? Давайте оставим прежние значения гиперпараметров – 30 эпох, скорость 0,5, размер мини-пакета 10. Однако, нам нужно поменять параметр регуляризации. Дело в том, что размер n обучающего набора скакнул от 1000 до 50 000, а это меняет фактор ослабления весов 1 — ??/n. Если мы продолжим использовать ?=0,1, это означало бы, что веса ослабляются куда меньше, и в итоге эффект от регуляризации уменьшается. Мы компенсируем это, приняв ?=5,0. Хорошо, давайте обучим нашу сеть, сначала повторно инициализировав веса:
Мы получаем результаты: Много всего приятного. Во-первых, наша точность классификации на проверочных данных подросла, с 95,49% без регуляризации до 96,49% с регуляризацией. Это серьёзное улучшение. Во-вторых, можно видеть, что разрыв между результатами работы на обучающем и проверочном наборах гораздо ниже, чем раньше, менее 1%. Разрыв всё равно приличный, но мы, очевидно, достигли значительного прогресса в уменьшении переобучения. Наконец, посмотри, какую точность классификации мы получим при использовании 100 скрытых нейронов и параметра регуляризации &lambda=5,0. Не буду приводить подробный анализ переобучения, это делается просто ради интереса, чтобы посмотреть, насколько большой точности можно достигнуть с нашими новыми хитростями: функцией стоимости с перекрёстной энтропией и регуляризацией L2.
Конечный результат – точность классификации в 97,92% на подтверждающих данных. Большой скачок по сравнению со случаем с 30 скрытыми нейронами. Можно подстроить ещё немного, запустить процесс на 60 эпох с ?=0,1 и ?=5,0, и преодолеть барьер в 98%, достигнув точность 98,04 на подтверждающих данных. Неплохо для 152 строк кода! Я описал регуляризацию как способ уменьшения переобучения и увеличения точности классификации. Но это не единственные её преимущества. Эмпирически, испробовав через множество запусков нашу сеть MNIST, меняя каждый раз веса, я обнаружил, что запуски без регуляризации иногда «застревали», очевидно, попав в локальный минимум функции стоимости. В итоге разные запуски иногда выдавали сильно разные результаты. А регуляризация, наоборот, позволяет получать гораздо легче воспроизводимые результаты. Почему так получается? Эвристически, когда у функции стоимости нет регуляризации, длина вектора весов, скорее всего, будет расти, при прочих равных. Со временем это может привести к очень большому вектору весов. А из-за этого вектор весов может застрять, показывая примерно в одном и том же направлении, поскольку изменения из-за градиентного спуска делают лишь крохотные изменения в направлении при большой длине вектора. Я считаю, что из-за этого явления нашему алгоритму обучения очень тяжело как следует изучить пространство весов, и, следовательно, тяжело найти хороший минимум функции стоимости. Источник: habr.com Комментарии: |
|