Вначале был нейрон: понимание градиентного спуска, обратного распространения, линейной регрессии, логистической регрессии, автоэнкодеров, сверточных нейронных сетей и VGG16. С наглядными пособиями и практическим программированием на Python и Keras.

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

Прочитав эту статью, вы наконец раскроете тайну глубокого обучения.

У вас также будут содержательные открытые вопросы. В этом весь смысл (глубокого) обучения, верно?

Начнем с рассказа.

Человек, который жил в будущем

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

Итак, какова связь с глубоким обучением? Продолжайте читать, и вы будете в восторге. Старший сын фермера поставил следующий эксперимент. Он взял образцы зерна и положил в мешок количество, примерно соответствующее величине урожая за каждый предыдущий год. Каждый мешок представлял год в возрастающем порядке. Затем он просит своего младшего брата положить палку на верхнюю часть пакетов, чтобы палка не упала и была хорошо сбалансирована, как показано на картинке с этой статьей.

Это изображение дало старику представление об урожае, который он мог бы ожидать в ближайшие годы, если предположить, что тенденция сохранится. Неужели его сын только что изобрел линейную регрессию за сотни лет до Фрэнсиса Гальтона (извините, сэр)?

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

Продолжайте читать, скоро мы займемся глубоким обучением. Люди одержимы будущим. Мы хотим знать, пойдет ли завтра дождь, поженимся ли мы в следующем году, станем ли мы, наконец, богатыми и когда. В прошлом это были любимые вопросы, которые задавали оракулам (а не компании-разработчику программного обеспечения Oracle). Предположительно, оракулы были людьми с особой квалификацией, которые предсказывали будущее на основе реальных данных, таких как линии на руке, созвездие звезд или вкус крови.

Возможность предсказывать будущее - не всегда хорошо. Кассандра Троянская обладала даром предвидения. К ее большому сожалению, Аполлон проклял ее, что никто не поверит ее предсказаниям. Поэтому ее предупреждения об уничтожении Трои были проигнорированы, и дела у нее пошли не так хорошо. Сегодня компании, организации и правительства ищут свою собственную Кассандру Трои, нанимая специалистов по данным, оракулов современности. Поскольку некоторые специалисты по обработке и анализу данных и специалисты по машинному обучению хотят быть как можно более скрытыми, чтобы получить большее значение, как оракулы прошлого, они все время предпочитают использовать так называемую технологию Deep Learning. . Кроме того, потому что это работает. Не только для предсказания будущего, но и для понимания настоящего, делая выводы и классифицируя всевозможные вещи. Вы можете посмотреть эту статью, чтобы убедиться, что мы можем делать с помощью глубокого обучения.

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

Линейная регрессия с нейроном

Сначала мы рассмотрим линейную модель сына фермера. Он использовал год как показатель количества урожая (его величины). Проведя наиболее подходящую совпадающую линию, которая отражает тенденцию изменения количества в течение многих лет, он смог спрогнозировать количество урожая на следующие годы. Математически он нашел линию Ŷ за годы X с точкой пересечения β0 и наклоном β1.

Аналитическое решение линейной регрессии

Учитывая реальные измерения для Y и соответствующий предиктор X, мы можем вычислить наклон и точку пересечения следующим образом.

Изображение стоит тысячи слов, так же как и код Python. Чтобы построить красивые графики и изучить модель, мы воссоздадим данные, которые использовал сын фермера. Давайте создадим 100 искусственных наборов случайных измерений вдоль прямой линии на плоскости, представленной линейным уравнением. Мы распределяем эти точки вдоль линии равномерно в интервале от -2 до 3. Затем мы добавляем случайное нормально распределенное значение со стандартным отклонением 1 и средним 0 к каждому значению Y. Наконец, мы используем приведенную выше формулу для вычисления точки пересечения и наклона.

Как видно на изображении выше, идея сына фермера побеждает. Мы можем предсказать Y для любого значения X, поскольку нам известна линия регрессии, определяющая поведение Y. Итак, можем ли мы сделать то же самое с искусственной нейронной сетью? Во-первых, нам нужно определить, что на самом деле является искусственной нейронной сетью.

Биологический нейрон

Что было первым? Нейробиология или искусственные нейронные сети? Как бы то ни было, идея искусственного нейрона, похоже, исходит от нейронов в нашей голове. Наш мозг состоит из 100 миллиардов нейронов. Когда электрические сигналы проходят через дендриты в ядро ​​нейрона, электрический заряд накапливается. Когда клетка достигает определенного уровня заряда, порога, она активируется, посылая электрический сигнал через аксон. Нейроны по-разному оценивают разные входящие сигналы, когда решают, когда стрелять. Некоторые считают, что искусственные нейронные сети имитируют процесс присвоения разных весов разным дендритам (входам).

Искусственный нейрон

Один искусственный нейрон принимает входной сигнал X, применяет (линейное) аффинное преобразование с помощью весов W для получения временное значение h. Затем он передает это значение через функцию активации для получения вывода. В нашем примере линейной регрессии X может быть числом, скажем 2. Аффинное преобразование будет использовать точку пересечения и наклон, хранящиеся в векторе W, для преобразования входных данных в для возврата, допустим, h = 5. Последующее значение пройдет активацию, которая в нашем случае является линейной функцией, для вывода, скажем, Y = h = 5.

Искусственный нейрон и градиентный спуск

Ранее мы видели, что точку пересечения и наклон линии регрессии можно вычислить напрямую, используя аналитическую формулу. Может ли искусственный нейрон, как мы только что описали, найти эти значения без использования какой-либо формулы? Мы могли бы использовать следующую стратегию: мы можем выбрать случайные значения для точки пересечения и наклона, скажем W = (- 1, 3), затем нейрон может вычислить соответствующую линию регрессии и сравнить ее с истинные значения Y. Затем мы сможем вычислить разницу между выходом нейрона и истинным Y, то есть потерями. В нашем случае среднеквадратичная ошибка является хорошей функцией потерь, мы вызываем L. Мы будем повторять процесс выбора случайных значений W до тех пор, пока потеря не станет достаточно маленькой или пока мы не устанем пытаться. Эта стратегия может хорошо работать для одного нейрона. Однако, если у нас есть два или тысячи нейронов, мы можем потратить на поиски всю жизнь. Вот почему эта стратегия звучит так безумно, что людям пришла в голову идея получше под названием градиентный спуск. Это похоже на спуск по заснеженной альпийской горе на лыжах для фристайла с вершины по кратчайшему пути вниз в долину. Не быть убитым.

Градиентный спуск - это инструмент для поиска значений для W, которые минимизируют функцию потерь L, глядя на производную этой функции по W . Допустим, мы выбрали W = (- 1, 3) и рассчитали потери для этих значений, теперь нам нужно решить, какие следующие значения W попробовать в чтобы убыток уменьшался. Идея состоит в том, чтобы вычислить производную потерь, скажем, по перехвату, и проверить ее признаки. Если производная положительна, это означает, что потери увеличиваются, поэтому нам нужно попробовать меньшую точку пересечения. Если производная отрицательна, потери уменьшаются, поэтому мы можем продолжать пробовать большие значения наклона. Если производная равна нулю, мы достигли минимума потерь, надеюсь, глобального. Мы можем остановиться и считать W оптимальным весом, который минимизирует потери. Градиентный спуск требует вычисления производных, что может стать кошмаром, если у нас нет хорошего инструмента, такого как Matlab. Благодаря обратному распространению нам даже не нужны такие инструменты, как мы увидим позже.

Линейная регрессия с Керасом

Давайте посмотрим на практике, как наш нейрон будет выполнять задачу линейной регрессии. Мы используем Keras, библиотеку Python и хороший компаньон для экспериментов по глубокому обучению. Мы создаем модель с одним нейроном, скалярным входом, скалярным выходом, аффинным преобразованием с весом и смещением и линейным выходом. Затем мы обучаем наш нейрон точкам данных, используя оптимизатор стохастического градиентного спуска. Функция потерь - это среднеквадратичная ошибка. Оптимизатор выполнит 5 итераций (эпох). Для простоты мы не масштабируем данные.

Вуаля! Один нейрон смог предсказать почти ту же линию регрессии (зеленый), которую мы ранее рассчитали аналитически (оранжевый). Прогнозируемые значения для наклона и пересечения очень близки, как показано на изображении выше. Показатели R2 (показатель пригодности) в обоих случаях также выглядят одинаково. Кажется, искусственная нейронная сеть действительно работает! А что, если мы немного усложним?

Нелинейная регрессия с нейронами

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

Модель трех нейронов

Очевидно, что отдельный нейрон с линейной активацией не сможет уловить поведение в этих новых данных. Первая мысль - изменить функцию линейной активации и вместо нее использовать функцию формы S. Сигмовидная функция - хороший кандидат, который в значительной степени используется в глубоком обучении. Сигмоид идеально отражал бы тенденцию к увеличению, наблюдаемую в наших данных. Тенденция к уменьшению также может быть зафиксирована с помощью зеркальной сигмоиды. Таким образом, нам нужны два сигмоида, следовательно, два нейрона и третий нейрон, который суммирует оба сигмоида. Соответствующая архитектура показана на изображении ниже.

Первый нейрон примет скаляр X в качестве входных данных, затем применит аффинное преобразование с использованием веса W1 и смещения. В результате будет произведена сигмовидная активация h1. Нечто подобное произойдет во втором нейроне, который произведет h2. Теперь оба числа h1 и h2 будут переданы в третий нейрон, который выполнит аффинное преобразование, применив веса W31 к h1 и W32 на h2, наконец, добавив смещение . Получившийся q пройдет линейная активация для получения формы с одним горбом.

Прямой проход с искусственными нейронными сетями

Давайте построим эту сеть на Python с нуля, без Keras. Как мы видели в предыдущем разделе, сеть имеет в общей сложности 7 весов (и смещения). Мы присваиваем значения 7 весам вручную, выполняем прямой проход, используя данные для функции горба, и строим выходные данные из сети на том же графике, что и истинные значения Y. Мы корректируем веса вручную, пока графики не будут совпадать как можно точнее. Таким образом, мы моделируем так называемый прямой проход, который выполняется Керасом при обучении сети.

Нелинейная регрессия с Keras

Как и Кассандра из Трои, мы смогли угадать идеальные значения для W, так что выходные данные сети превосходят данные. Хотя большинство специалистов по данным могут творить чудеса, не все люди обладают этим даром. К счастью, для простых людей есть другой способ сделать это. Это необходимо для использования библиотеки, такой как Keras, для запуска оптимизатора градиентного спуска, который изо всех сил пытается найти для нас эти 7 весов. Это то, что мы иллюстрируем в приведенном ниже коде.

После 50000 эпох обучения сеть достигает 96,69% ​​балла R2. На приведенном выше графике показан его прогноз по сравнению с тем, который мы ранее получили с помощью ручной настройки весов. Выглядит потрясающе, не правда ли? Имея 3 нейрона, точки данных X и Y, сеть может точно настроить себя в соответствии с данными. Он узнал форму данных без дальнейшего понимания. Ниже мы можем визуально увидеть, как поиск лучшего W сводился к наименьшим потерям. Если мы позволим оптимизатору работать для дополнительных эпох, мы в конечном итоге достигнем 100% соответствия. Некоторые читатели этой статьи уже скрипят зубами и думают о переобучении и масштабировании. Что ж, давайте пока будем счастливы и вернемся к этой горячей теме позже.

Этот результат является дополнительным доказательством, подтверждающим утверждение о том, что искусственные нейронные сети обладают способностью фиксировать нелинейные зависимости в данных. Поэтому глубокое обучение работает? Ну, мы тут немного обманули. Мы разработали сеть на основе наших предварительных знаний о двойной сигмоидальной форме данных и, следовательно, выбрав сигмоид в качестве функции активации. Данные из реального сценария не всегда имеют такую ​​четкую форму, и мы будем экспериментировать, чтобы найти правильную архитектуру сети. Рано или поздно мы внесем свой взгляд на мир в сетевую архитектуру, превратив ее в предвзятую модель. Вы можете посмотреть другую мою статью об ответственной науке о данных. А пока предположим, что все мы хорошие парни. Однако вопрос, почему работает глубокое обучение, остается открытым.

Логистическая регрессия с Керасом

Нашему фермеру не очень понравилась модель горба, особенно ее вторая часть, и он посоветовал ему ожидать снижения урожая. Он скорее хотел знать, в какие годы ожидать хорошего урожая. Ниже мы создаем набор данных, который бы отражал ситуацию. Годы ниже 0 классифицируются как годы с неурожаем, а годы после 0 - с хорошим урожаем.

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

Градиентный спуск в логистической регрессии

Проблема классификации, которую мы только что решили, является хорошим примером того, как попасть в темный мир градиентного спуска и обратного распространения. Напомним, что в нашем вышеупомянутом нейроне вход прошел через аффинное преобразование, а результат был передан в сигмовидную активацию. Таким образом, на выходе будет значение от 0 до 1, то есть вероятность хорошего урожая. Ниже мы видим выражение этого вывода P (Y = 1). Обратите внимание, что аффинное преобразование X зависит от двух параметров β0 и β1.

Во время обучения для любого ввода Xi нейрон может вычислить вероятность Pi и сравнить ее с истинным значением Yi. Ошибка обычно рассчитывается с использованием двоичной кросс-энтропии. Он выполняет ту же работу, что и введенная нами ранее среднеквадратическая ошибка. Двоичная кросс-энтропия измеряет, насколько далеко от истинного значения Yi (которое равно 0 или 1) находится прогноз Pi. Формула, используемая для вычисления бинарной кросс-энтропии Li, приведена ниже.

Как видите, потери зависят от весов β0 и β1. После того, как оптимизатор градиентного спуска выбрал случайные веса, он выбирает случайный Xi, а затем выполняет прямой проход для вычисления потерь. Оптимизатор повторяет этот расчет для всех точек входных данных, если мы используем базовый градиентный спуск, или только для небольших пакетов данных, если мы используем стохастическую версию. Полная потеря получается суммированием всех индивидуальных потерь. После того, как оптимизатор вычислит потери, он вычислит свою производную по весам. В зависимости от знака производной, вес будет обновляться либо в положительную, либо в отрицательную сторону.

Мы знаем, что хотим пойти в направлении, противоположном производной, и мы знаем, что хотим сделать шаг, пропорциональный производной. Скорость обучения λ - это то, что контролирует эту пропорцию для каждого веса W (β0 или β1).

Обратное распространение в логистической регрессии

Как вы можете видеть на изображении выше, обновление весов требует вычисления частных производных потерь по каждому весу. Как мы это делаем? Что ж, для этого мы можем использовать математику средней школы. На изображении ниже мы пытаемся вычислить вывод функции потерь кросс-энтропии относительно β0 и β1.

Для сети с одним нейроном это отличное решение. Но представьте себе сеть с сотнями нейронов, с которой мы обычно сталкиваемся при глубоком обучении. Бьюсь об заклад, вы не хотите вычислять полученную производную. Даже если вам это удастся, вам придется обновлять свои формулы каждый раз, когда архитектура сети изменяется, даже немного. Здесь в игру вступает обратное распространение. Алгоритм обратного распространения сигналов был впервые представлен в 1970-х годах, но его важность не была полностью оценена до статьи Джеффри Хинтона 1986 года.

Обратное распространение использует цепное правило, которое является удобной мнемоникой для написания производных вложенных функций. Например, если у нас есть сеть с одним нейроном, который подает сигнал на второй и, наконец, на третий, чтобы получить результат. Функция общих потерь f является функцией функции потерь g первых двух нейронов, аналогично g является функцией функции потерь h первого нейрона.

По сути, пока мы идем вперед от входов, вычисляя выходы каждого нейрона, до последнего нейрона, мы также уже оцениваем крошечные компоненты производной. В приведенном выше примере мы можем вычислить dh / dx уже при прохождении вперед через первый нейрон. Затем мы можем вычислить dg / dh при прохождении вперед через второй нейрон. Наконец, мы начинаем вычислять df / dg, проходя в обратном направлении через нейроны и повторно используя все уже вычисленные элементы. Это источник обратного распространения имени. Есть несколько вариантов реализации и разновидностей этой техники. Для простоты здесь мы сохраняем простоту.

Чтобы проиллюстрировать, как работают правило цепочки и обратное распространение, давайте вернемся к функции потерь для нашей 1-нейронной сети с сигмовидной активацией. Функция потерь была определена как двоичная кросс-энтропия, которую можно разделить на две части A и B, как показано ниже.

Давайте подробнее рассмотрим часть А функции потерь. Его можно разделить на блоки, выделенные красными полями на изображении ниже.

Обратное распространение требует вычисления производной этой функции в любой заданной точке данных X для любого заданного веса W. Это делается путем вычисления производной каждого блока и объединения всех данных с помощью правила цепочки. Ниже мы видим, как это будет работать для X = 3 и W = 3.

Все, что нам нужно, это уметь вычислять производные небольших блоков (названных выше переменными). Такие блоки известны, потому что обычно известны функции активации. Они могут быть сигмовидными, линейными, ReLu и т. Д. Это дифференцируемые функции с известными производными. Полный список модных функций активации можно найти здесь. Следовательно, приведенные выше вычисления могут быть построены во время выполнения с использованием вычислительного графа. Керас может посмотреть на вашу сетевую архитектуру и функции активации, используемые в каждом нейроне, чтобы построить вычислительный граф во время компиляции модели. Этот график используется во время обучения для выполнения прямого и обратного распространения. Пример расчетного графика для функции потерь кросс-энтропии представлен ниже.

Кластеризация с нейронами

Понимание того, как работают градиентный спуск и обратное распространение, - отличный шаг к пониманию того, почему на самом деле работает глубокое обучение. Что ж, мы еще не зашли так глубоко. До сих пор мы использовали всего 3 нейрона. Наш фермер может утверждать, что взаимосвязь между годами и количеством урожая слишком сложна, чтобы ее можно было представить только двумя классами: хорошим и плохим. В этом разделе мы рассмотрим проблему кластеризации с помощью искусственной нейронной сети. Давайте смоделируем некоторое облако данных, распределенное по трем группам, представляющим качество уборки. Рассмотрим три точки на плоскости (x, y) с координатами (-2,0), (0,1.7) и (2.1,0). Вокруг каждого из этих трех центров мы создаем облако из 100 случайно сгенерированных точек. Для радиального расстояния любой из этих точек от ее центра мы используем случайное нормальное распределение. Для угловой координаты любой одной из точек «облака» мы используем равномерное распределение.

Теперь мы создадим двухслойную искусственную нейронную сеть, которая может предсказать, принадлежит ли случайно сгенерированная точка на плоскости к облаку 0, 1 или 2. Входной слой имеет 50 нейронов (мы углубляемся)! Он принимает два значения (x, y). К аффинному преобразованию входа применяется функция активации ReLU. Результат передается в выходной слой с 3 нейронами, которые используют функцию активации softmax для прогнозирования одного из трех классов облаков. Оптимизатор стохастического градиента используется для решения задачи классификации оценки 303 весов и смещений путем минимизации категориальной кросс-энтропии, используемой в качестве функции потерь. Мы разбиваем данные на 50 точек данных для обучения классификатора и 50 для проверки. Мы тренируемся по 5 баллов в течение 20 эпох. После обучения мы также выполняем прогноз на тестовых наборах. Мы используем argmax для преобразования предсказанного категориального вектора в исходные метки перед отображением.

Как показано выше, нейронная сеть хорошо справляется с разделением классов в тестовом наборе (правый график). Некоторым выбросам, обнаруженным в исходных данных (слева), сеть (справа) присваивает другой ярлык, чтобы создать четкие границы. Мы достигаем точности классификации 95,33% на тестовых данных.

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

Теперь внук внука нашего фермера заинтересовался глубоким обучением! Направляйтесь прямо на http://playground.tensorflow.org, чтобы создать свою собственную искусственную нейронную сеть, визуально изменяя слои, нейроны, функцию активации, обучение и тестирование прямо в браузере. Когда вы закончите, вернитесь сюда, чтобы получить более интересные вещи.

Автоэнкодер для шумоподавления изображений

Читатели, которых к настоящему времени не впечатлили, уже знают, почему глубокое обучение работает. Остальным из нас мы теперь рассмотрим пример более глубокой сетевой архитектуры. Автоэнкодер состоит из пары двух связанных сетей: модели кодировщика и модели декодера. Цель автоэнкодера - найти способ кодирования ввода в сжатую форму (скрытое пространство) таким образом, чтобы декодированная версия была как можно ближе к вводу. Модель кодировщика превращает входные данные в небольшое плотное представление. Модель декодера можно рассматривать как генеративную модель, способную генерировать определенные функции. И кодер, и декодер обычно обучаются как единое целое. Функция потерь наказывает сеть за создание выходных данных, которые отличаются от входных. Следовательно, кодировщик учится сохранять столько релевантной информации, которая необходима при ограничении скрытого пространства, и умело отбрасывает нерелевантные части, например шум. Декодер учится принимать сжатую скрытую информацию и преобразовывать ее в полностью безошибочный ввод. Автоэнкодер может быть полезен для уменьшения размерности и шумоподавления изображений, но также может быть успешным в неконтролируемом машинном переводе (вау!).

Ниже мы определяем простейшую архитектуру автокодировщика, обрабатывающего изображения зашумленных рукописных цифр. Предоставляем в сеть оригинальные изображения x, а также их зашумленную версию x ~. Сеть пытается восстановить свой выходной сигнал x ’, чтобы он был как можно ближе к исходному изображению. Поступая так, он узнает, как удалить шум с любой рукописной цифры.

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

Вход: изображение размером 28 x 28 в оттенках серого. Следовательно, вход - это вектор из 784 элементов.

Кодировщик: один плотный слой с 64 нейронами. Следовательно, скрытое пространство будет иметь размер 64. Используемая функция активации - это выпрямленные единицы (ReLu), выбранные из лучших практик. Функция активации привязана к каждому нейрону в слое и определяет, должен ли он быть активирован («активирован») или нет, в зависимости от того, является ли вход каждого нейрона релевантным для предсказания автоэнкодера. Функция активации также помогает нормализовать выходной сигнал каждого нейрона до диапазона от 1 до 0.

Декодер: один плотный слой с 784 нейронами, соответствующий изображению в оттенках серого 28x28. Функция активации сигмоида используется как лучший метод для задачи классификации (ввод в кодировщик по сравнению с выходом из декодера).

Оптимизатор: мы используем двоичную кросс-энтропию как функцию потерь и Adadelta как оптимизатор для минимизации функции потерь.

Данные: мы используем цифры MNIST для генерации синтетических зашумленных цифр, применяя матрицу гауссовского шума и обрезая изображения между 0 и 1. Ниже мы отображаем некоторые из зашумленных цифр.

Мы все еще можем распознать цифры, но с трудом. Поэтому мы хотим использовать наш автокодировщик, чтобы научиться восстанавливать исходные цифры. Мы делаем это, настраивая автоэнкодер более чем на 100 эпох, используя зашумленные цифры в качестве входных и исходные шумоподавленные цифры в качестве цели. Таким образом, автоэнкодер минимизирует разницу между зашумленными и чистыми изображениями. Делая это, он узнает, как удалить шум из любой невидимой рукописной цифры, которая была произведена с аналогичным шумом.

Ниже мы сопоставляем зашумленные входные изображения с их очищенной версией.

  • общий шум удаляется очень хорошо. Белые точки, искусственно введенные на исходные изображения, исчезли с очищенных изображений. Цифры можно распознать визуально. Например, зашумленная цифра «4» вообще не читалась, теперь мы можем прочитать ее очищенную версию.
  • шумоподавление имеет обратную сторону в отношении качества информации. Реконструированные цифры как-то размыты. Декодер добавил некоторые функции, которых не было в исходном изображении, например 8-я и 9-я цифры ниже едва различимы.

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

Сверточные нейронные сети

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

А теперь давайте построим глубокую сеть. Мы начинаем с первого сверточного слоя Conv2D, который имеет 16 фильтров, каждый с размером 3x3. Отступы такие же, шаг равен 1, поэтому выходная карта объектов будет иметь форму 28x28x16. Мы применяем функцию активации ReLu к этому выходу после добавления к нему смещения. Свертка вызывает повторение информации, поступающей из соседних областей изображения, что приводит к высокой размерности. Пул берет область вывода сверточного слоя и возвращает агрегированное значение: обычно максимальное, но может использоваться среднее, минимальное или любая функция.

Мы добавляем слой MaxPooling2D размером 2x2, шагом 1 и таким же отступом. Это означает, что мы возьмем максимальное значение 2x2 фрагментов и перейдем на 1 шаг к следующему фрагменту. Результат объединения будет дополнен нулями, чтобы иметь тот же размер, что и вход. Объединение всегда выполняется после применения функции активации к свертке.

CNN работают лучше всего при рассмотрении нескольких шкал. Поэтому мы дублируем сверточный и максимальный слои объединения еще раз. В результате кодировщик выводит представление изображения в форме 7x7x32. Это связано с тем, что входное изображение 28x28x1 сворачивается каждым из 32 фильтров 3x3 в первом слое Conv2D, возвращая пространство функций размером 28x28x32. MaxPooling уменьшает это представление до половины 14x14x32. Второй слой Conv2D сворачивает каждое из представлений 14x14x32, используя набор из 32 фильтров 3x3. Это приводит к пространству признаков размером 14x14x32. Последний слой MaxPooling уменьшает представление наполовину, в результате получается форма 7x7x32.

Декодер имеет ту же архитектуру, что и кодер, с выравниванием слоев в обратном порядке. Мы используем слой UpSampling, чтобы восстановить уменьшение размерности, которое было выполнено MaxPooling в кодировщике. Наконец, мы добавляем сверточный слой, который восстанавливает количество каналов в последнем представлении до 1. Функция активации сигмоида используется для решения проблемы классификации, где двоичный результат отражает, насколько сходно декодированное изображение с входным. Мы можем наблюдать, как декодирующая часть автоэнкодера восстановила исходную форму изображения (28x28x1).

Полная сеть имеет 28 353 веса и смещения для тренировки. Мы используем бинарную кросс-энтропию как функцию потерь и Adadelta как оптимизатор для минимизации функции потерь. После 20 эпох автоэнкодер CNN имеет значение потери последовательности / теста около 0,098, по сравнению с более высокими потерями 0,1235, которые мы имели с плотным автоэнкодером. Наш автоэнкодер с CNN довольно хорошо работает с невидимыми изображениями. По сравнению с простым автоэнкодером с 1 плотным скрытым слоем из предыдущего раздела, изображения с шумоподавлением выглядят намного лучше.

Становиться глубже

Способ объединения сверточных слоев - это больше искусство, чем наука. Не бойтесь взглянуть на сеть VGG ниже, она была предложена в 2014 году для классификации 14 миллионов изображений по 1000 классам с точностью теста 92,7%. Его тренировали в течение 2 недель, чтобы оценить свои 14 714 688 весов. Ужасный! Таких сверхмассивных сетей больше: GoogLeNet, ResNet, DenseNet, MobileNet, Xception, ResNeXt и многие другие.

Рекомендуемый и очень эффективный подход к глубокому обучению - использовать одну из этих предварительно обученных сетей. Предварительно обученная сеть - это просто сохраненная сеть, предварительно обученная на большом наборе данных, которая может эффективно действовать как общая модель реального мира. Извлечение признаков - это один из способов использования представлений, изученных предварительно обученной сетью, путем взятия сверточной базы предварительно обученной сети, пропуска через нее новых данных и обучения нового простого классификатора поверх вывода с использованием нового небольшого набора данных , как показано ниже. Альтернативный метод состоит из замораживания базы предварительно обученной сети, добавления простого классификатора и обучения всей сети. Другая альтернатива, называемая точной настройкой, заключается в размораживании определенных слоев базы перед тренировкой.

Заключение

В этой статье мы использовали подход к глубокому обучению на основе архитектуры нейронной сети. Вместо того, чтобы напрямую объяснять, почему алгоритмы глубокого обучения постепенно изучают представление сложных входных данных по мере их прохождения через каждый уровень нейронной сети, мы начали с малого, с одного нейрона. С помощью практических примеров и кода Python мы решили основные задачи регрессии с помощью искусственных нейронных сетей и постепенно создали автоэнкодер со сверточными слоями. Мы продемонстрировали процесс обучения с помощью градиентного спуска и обратного распространения ошибки. Вскоре мы представили трансферное обучение с использованием предварительно обученных сверхмассивных искусственных нейронных сетей, таких как VGG16.

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

Охват Deep Learning в одной статье - это шутка, мы не пытались ее шутить. Прекрасны классические книги «Глубокое обучение» Яна Гудфеллоу и «Глубокое обучение с помощью Python» Франсуа Шоле. отправные точки.

Почему работает глубокое обучение? Это открытый вопрос. Слава Богу.

Спасибо за чтение. Посмотрите мою статью о байесовском подходе в машинном обучении ниже.