Рохан # 4: проблема исчезающего градиента

О нет - препятствие для глубокого обучения!

Это четвертая запись в моем путешествии по расширению моих знаний об искусственном интеллекте в 2016 году. Узнайте больше о моих мотивах в этом вводном посте.

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

Сейчас лето, и вы недавно прочитали мой пост на Medium об алгоритме обратного распространения ошибки. В восторге от того, что вы взломаете свою собственную реализацию, вы создаете глубокую многослойную нейронную сеть и начинаете запускать программу. Но, к вашей пользе, тренироваться либо нужно бесконечно, либо неточно. Почему‽ Вы думали, что нейронные сети - это самое современное искусство, не так ли!

Фактически, я на какое-то время застрял в этом вопросе.

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

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

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

Вы получите удлиненную функцию стоимости, например следующую:

Сравните эту форму, например, со следующей, более оптимальной:

Поскольку последний имеет более крупные градиенты, градиентный спуск может сходиться намного быстрее.

Это не единственная проблема. Когда градиенты становятся слишком маленькими, также становится трудно представить числовые значения в компьютерах. Мы называем это истощением - противоположностью переполнения.

Хорошо. Небольшие градиенты = плохие новости, понятно. Тогда возникает вопрос: существует ли эта проблема? Во многих случаях это действительно так, и мы называем это проблемой исчезающего градиента.

Вспомните сигмовидную функцию, которая почти всегда использовалась как функция активации для ИНС в контексте классификации:

Сигмоидальная функция полезна, потому что она «сжимает» любое входное значение в выходной диапазон (0, 1) (где оно асимптотически). Это идеально подходит для представления вероятностей и классификации. Однако сигмовидная функция, наряду с функцией tanh, в последние годы потеряла популярность. Почему? Потому что они страдают от проблемы исчезающего градиента!

Давайте посмотрим на производную сигмовидной функции. Я предварительно рассчитал это для вас:

Теперь давайте изобразим это:

Вы говорите, что выглядит прилично. Присмотрись. Максимальная точка функции - 1/4, а функция асимптоты по горизонтали равна 0. Другими словами, выход производной функции стоимости всегда находится между 0 и 1/4. С математической точки зрения диапазон равен (0, 1/4]. Имейте это в виду.

Теперь перейдем к структуре нейронной сети и обратного распространения и их влиянию на размер градиентов.

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

Чтобы вычислить производную от первого веса, мы использовали цепное правило для «обратного распространения» следующим образом:

Давайте сосредоточимся на этих отдельных производных:

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

То же самое и со вторым:

В обоих случаях производная содержит производную сигмовидной функции. А теперь давайте соберем их вместе:

Напомним, что производная сигмовидной функции выводит значения от 0 до 1/4. Умножая эти две производные вместе, мы умножаем два значения в диапазоне (0, 1/4]. Любые два числа от 0 до 1, умноженные друг на друга, просто приведут к меньшему значению. Например, 1/3 × 1/3 равно 1/9.

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

Теперь посмотрим на величину терминов в нашем выражении:

На этом этапе мы умножаем четыре значения от 0 до 1. Это станет маленьким очень быстро. И даже если этот метод инициализации веса не используется, проблема исчезающего градиента, скорее всего, все равно возникнет. Многие из этих сигмовидных производных, умноженные вместе, будут достаточно малы, чтобы компенсировать другие веса, а другие веса могут захотеть сместиться в диапазон ниже 1.

Эта нейронная сеть не такая уж глубокая. Но представьте себе более глубокий, используемый в промышленном применении. По мере того, как мы возвращаемся назад, у нас будет гораздо больше маленьких людей, принимающих участие в продукте, создавая еще более крошечный градиент! Таким образом, с глубокими нейронными сетями проблема исчезающего градиента становится серьезной проблемой. Примечание: у нас могут быть даже взрывающиеся градиенты, если градиенты были больше 1 (набор чисел больше 1, умноженных вместе, даст огромный результат!) Это тоже нехорошо - они дико промахиваться.

Теперь давайте посмотрим на типичную ИНС:

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

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

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

В любом случае, что такое функция ReLU - Rectified Linear Unit? Это кусочная функция, которая соответствует:

Другой способ написания функции ReLU выглядит так:

Другими словами, когда вход меньше нуля, функция будет выводить ноль. В противном случае функция будет имитировать функцию идентификации. Вычислить функцию ReLU очень быстро.

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

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

Итак, решено! Наши производные больше не обращаются в нуль, потому что производная функции активации не ограничена диапазоном (0, 1).

Однако у ReLU есть одно предостережение: они «умирают» (выходной ноль), когда входной сигнал отрицательный. Во многих случаях это может полностью заблокировать обратное распространение, потому что градиенты будут просто нулевыми после того, как одно отрицательное значение было введено в функцию ReLU. Это также будет проблемой, если будет изучен большой член отрицательного смещения / постоянный член - взвешенная сумма, введенная в нейроны, может оказаться отрицательной, потому что положительные веса не могут компенсировать значимость члена смещения. Также приходят на ум отрицательные веса или отрицательные входные данные (или некоторая комбинация, дающая отрицательную взвешенную сумму). Таким образом, мертвый ReLU будет выводить одно и то же значение почти для всех ваших действий - ноль. ReLU не могут «оправиться» от этой проблемы, потому что они ни в коем случае не будут изменять веса, поскольку не только выход для любого отрицательного входного нуля, но и производная тоже. Никаких обновлений для изменения (например) члена смещения, чтобы он имел меньшую отрицательную величину, чтобы нейронная сеть могла избежать повреждения всей сети. Однако не всегда бывает все, что взвешенная сумма оказывается отрицательной; и мы действительно можем инициализировать веса только положительными и / или нормализовать ввод между 0 и 1, если нас беспокоит вероятность возникновения такой проблемы.

РЕДАКТИРОВАТЬ: Оказывается, есть несколько чрезвычайно полезных свойств исчезновения градиентов. В частности, идея «разреженности». Так что во многих случаях блокировка обратного распространения может быть преимуществом. Подробнее об этом в ответе на StackOverflow:



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

РЕДАКТИРОВАТЬ: Похоже, что значения в диапазоне 0,2–0,3 встречаются чаще, чем что-то вроде 0,01.

Вместо вывода нуля при отрицательном входе функция будет выводить очень плоскую линию с градиентом ε. Обычное значение для ε - 0,01. Результирующая функция представлена ​​на следующей диаграмме:

Как видите, обучение будет небольшим с отрицательными входами, но, тем не менее, будет существовать. В этом смысле дырявые ReLU не умирают.

Однако ReLU / дырявые ReLU не всегда оптимальны - результаты с ними были непоследовательными (возможно, потому, что из-за небольшой константы в некоторых случаях это могло снова вызвать исчезающие градиенты? - при этом, как говорится, мертвые единицы снова не все это случается часто). Другая примечательная проблема заключается в том, что, поскольку выходной сигнал ReLU не ограничен между 0 и 1 или -1 и 1, как tanh / sigmoid, активации (значения в нейронах в сети, а не градиенты) могут фактически взорваться с чрезвычайно глубокие нейронные сети, такие как повторяющиеся нейронные сети. Во время обучения вся сеть становится хрупкой и нестабильной, поэтому, если вы обновите веса в неправильном направлении, даже малейшее, активации могут взорваться. Наконец, даже несмотря на то, что производные ReLU равны 0 или 1, наше общее выражение для производной содержит веса, умноженные на. Поскольку веса обычно инициализируются как

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

Вы также можете спросить: кстати, ReLU не сжимают значения в вероятность, так почему они так часто используются? Можно легко прикрепить сигмовидную / логистическую активность к концу нейронной сети для сценария бинарной классификации. Для нескольких выходов можно использовать softmax function, чтобы создать распределение вероятностей, которое складывается с 1.

Заключение

Было приятно писать эту статью, потому что это был мой первый шаг к тонкостям и практике машинного обучения, а не просто рассмотрение теоретических алгоритмов и расчетов. Проблема исчезающего градиента была основным препятствием на пути к успеху глубокого обучения, но теперь, когда мы преодолели ее с помощью нескольких различных методов инициализации веса (о которых я говорил меньше сегодня), подготовки функций (посредством пакетной нормализации - центрирование всех входных функций значения до нуля) и функций активации, поле будет процветать - и мы уже видели это с недавними нововведениями в игровом ИИ (AlphaGo, конечно!). За будущее многослойных нейронных сетей! 🍺