Оптимизаторы градиентного спуска

Понимание SGD, Momentum, Nesterov Momentum, AdaGrad, RMSprop, AdaDelta и ADAM

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

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

Но у реальной функции потерь обычно есть несколько минимумов, и есть только один глобальный минимум.

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

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

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

Обычно невозможно решить задачу минимизации с помощью сложной функции потерь с несколькими локальными минимумами и седловыми точками.

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

Исследователи изобрели оптимизаторы, чтобы не застревать в локальных минимумах и седловых точках и находить глобальный минимум с максимальной эффективностью.

В этой статье мы обсудим следующее:

  • SGD
  • Импульс
  • Нестеров Momentum
  • АдаГрад
  • RMSprop
  • АдаДельта
  • АДАМ

Функция потерь и градиент

Давайте сначала определимся с терминологией.

Нейронная сеть f принимает входные данные x и делает прогноз.

𝜃 - это набор сетевых параметров. Предположим, у нас есть N параметров, таких как веса и смещения в сети, 𝜃 будет вектором с N параметрами.

Например, x может быть изображением из MNIST размером 28x28 пикселей, а прогноз - это вектор вероятности для каждого из 10-значных чисел.

Функция потерь L сравнивает значения меток и прогнозируемые значения и возвращает скалярное значение потерь:

Чем меньше значение потерь, тем лучше качество прогноза.

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

Значение m - это размер пакета.

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

Градиент - это вектор частных производных, как показано ниже:

Каждый компонент градиента g является частной производной от J (𝜃) элементом 𝜃. Я использую g и ∇ J (𝜃) как взаимозаменяемые. Я в основном использую ∇ J (𝜃), но также использую g для краткости в некоторых случаях.

SGD

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

Мы обновляем каждый параметр в направлении, противоположном частной производной.

λ - это скорость обучения, которая определяет, сколько обновлять. Это гиперпараметр, который мы должны выбрать для тренировки.

Итак, мы делаем это для всех N параметров.

Мы можем записать вышесказанное в одну строку, как показано ниже:

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

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

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

Как видим, контролировать объем обновления параметров - нетривиальная задача.

Импульс

Другой способ выйти из локальных минимумов и седловых точек - использовать импульс.

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

Крутой склон добавлял бы больше и больше импульса.

Мы можем записать его, как показано ниже, для всех параметров:

v накапливает градиенты поэлементно.

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

Проблема с импульсом в том, что он может выходить за пределы глобального минимума из-за накопленных градиентов.

Нестеров Momentum

В импульсе Нестерова мы вычисляем градиенты в приближенном будущем (прогнозном) положении параметров.

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

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

Если градиенты становятся меньше, импульс Нестерова будет реагировать на это быстрее, чем исходный алгоритм импульса.

За исключением использования упреждающего градиента, это то же самое, что и SGD с исходным алгоритмом импульса.

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

Исходная формула обновления импульса

Формула обновления импульса Нестерова

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

Это похоже на спуск с холма. Вы можете идти быстро, когда склон продолжает быть крутым, но когда вы смотрите вперед и видите, что склон становится мелким, вы можете начать замедляться.

Примечания к планировщику скорости обучения

Кстати, есть еще один способ контролировать скорость обучения с помощью планировщика скорости обучения. Фреймворки глубокого обучения, такие как TensorFlow и PyTorch, предоставляют планировщики скорости обучения для корректировки скорости обучения. Вы можете постепенно снижать (или даже увеличивать в некоторых планировщиках) скорость обучения по пакетам / эпохам.

АдаГрад

SGD применяет одинаковую скорость обучения ко всем параметрам. При наличии импульса параметры могут обновляться быстрее или медленнее по отдельности.

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

В 2011 году Джон Дучи и др. опубликовал статью по алгоритму AdaGrad (Adaptive Gradient).

AdaGrad регулирует скорость обучения для каждого параметра в зависимости от квадрата суммы прошлых частных производных.

ε позволяет избежать проблемы деления на ноль. Реализация AdaGrad в PyTorch использует 1e-10 для ε.

Мы можем записать вышеуказанное для всех параметров следующим образом:

Символ точки в виде круга означает поэлементное умножение. Другими словами, мы возводим квадрат каждого элемента градиента. Квадратный корень из r также является поэлементной операцией.

Таким образом, если параметр имеет крутую частную производную, эффективная скорость обучения становится меньше. Для пологого склона эффективная скорость обучения становится относительно более значительной.

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

Джеффри Хинтон решил проблему AdaDelta с помощью RMSprop.

RMSprop

В 2012 году Джеффри Хинтон предложил RMSprop во время онлайн-обучения на Coursera. Он не публиковал статьи по этому поводу. Однако есть презентационный pdf, который мы можем увидеть. RMSprop стал широко известен, и PyTorch, и TensorFlow его поддерживают.

RMSprop вычисляет экспоненциально убывающее среднее квадратов градиентов. Вероятно, это легче понять, увидев формулу:

ρ управляет затуханием экспоненциально убывающего среднего квадрата градиентов. Хинтон предложил 0,9, тогда как в PyTorch по умолчанию 0,99.

Таким образом, влияние старых градиентов ослабевает в течение циклов обучения, что позволяет избежать проблемы снижения эффективных темпов обучения AdaGrad.

То же самое можно записать для всех параметров следующим образом:

Мы можем совместить RMSprop с импульсом.

Есть еще один вариант AdaGrad, решающий ту же проблему. Это называется АдаДельта.

АдаДельта

В 2021 году Мэтью Д. Цайлер опубликовал статью об AdaDelta. Он разработал AdaDelta независимо от Хинтона, но у него та же идея использования экспоненциально убывающего среднего квадрата градиентов - с некоторыми дополнительными настройками.

AdaDelta вычисляет скорость обучения λi для конкретного параметра следующим образом:

Значение di - это экспоненциально убывающее среднее квадрата дельты параметра (подробнее об этом скоро). Первоначально значение di равно нулю, поскольку у нас еще не было обновлений параметров.

Одним из преимуществ алгоритма является то, что AdaDelta адаптирует скорость обучения для каждого параметра, и мы не указываем глобальную скорость обучения, как в других оптимизаторах.

Используя адаптируемую скорость обучения для параметра, мы можем выразить дельту параметра следующим образом:

И мы обновляем параметр, как показано ниже:

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

Он работает как алгоритм импульса, поддерживающий скорость обучения на недавнем уровне (при условии, что v остается более или менее неизменным), пока не наступит значительный спад.

Мы можем записать вышеуказанное для всех параметров следующим образом:

Однако PyTorch поддерживает глобальную скорость обучения AdaDelta. Итак, обновление параметров AdaDelta в PyTorch работает, как показано ниже:

По умолчанию значение lr в PyTorch равно 1.0, поэтому он работает так же, как исходный алгоритм AdaDelta. Кроме того, мы можем контролировать глобальную скорость обучения с помощью планировщика скорости обучения, когда это имеет смысл.

АДАМ

В 2015 году Durk Kingma et al. опубликовал статью об алгоритме ADAM (Adaptive Moment Estimation).

Подобно RMSprop и AdaDelta, ADAM использует экспоненциально убывающее среднее квадратов градиентов.

Я использовал символ β в качестве имени коэффициента вместо ρ, который используется в разделе RMSprop. Причина в том, что ADAM также использует экспоненциально убывающее среднее значение градиентов.

Таким образом, v работает как импульс, поскольку он накапливает недавние градиенты при затухании прошлых градиентов.

ADAM инициализирует экспоненциально затухающие средние r и v как нули. Поскольку бета-версии обычно близки к 1 (например, в PyTorch, бета1 - 0,9, бета2 - 0,999), r и v, как правило, остаются близкими к нулю в течение, возможно, длительного времени. время, если у нас нет способа смягчить проблему.

Итак, ADAM использует следующую настройку:

Поскольку бета-значения близки к 1, знаменатели близки к нулю, что делает r и v больше, чем без такой корректировки.

Эффект от бета-корректировок в конечном итоге будет уменьшаться по мере увеличения значения t по мере обновления.

В целом формула обновления параметра выглядит следующим образом:

Итак, ADAM работает как комбинация RMSprop и инерции.

Мы можем написать выше для всех параметров:

Использованная литература:

Адаптивные субградиентные методы для онлайн-обучения и стохастической оптимизации (2011)

Джон Дучи, Элад Хазан, Йорам Сингер

Нейронные сети для машинного обучения: Лекция 6a Обзор мини-пакетного градиентного спуска (2012)

Джеффри Хинтон, Нитиш Шривастава, Кевин Сверски

ADADELTA: Метод адаптивной скорости обучения (2012)

Мэтью Д. Цайлер

Адам: метод стохастической оптимизации (2015)

Дидерик П. Кингма, Джимми Ба