Подтвердить что ты не робот

Gradient Descent vs Adagrad vs Momentum в TensorFlow

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

После уроков я не понимаю реальных и практических различий между тремя оптимизаторами потерь. Я смотрю на API и понимаю принципы, но мои вопросы:

1. Когда предпочтительнее использовать один вместо других?

2. Есть ли важные различия, которые нужно знать?

4b9b3361

Ответ 1

Вот краткое объяснение, основанное на моем понимании:

  • Импульс помогает SGD перемещаться по соответствующим направлениям и смягчает колебания в нерелевантных. Он просто добавляет часть направления предыдущего шага к текущему шагу. Это обеспечивает увеличение скорости в правильном направлении и смягчает колебания в неправильных направлениях. Эта фракция обычно находится в (0, 1) диапазоне. Также имеет смысл использовать адаптивный импульс. В начале обучения большой импульс будет только мешать вашему прогрессу, поэтому имеет смысл использовать что-то вроде 0,01, и как только все высокие градиенты исчезнут, вы можете использовать больший импульс. Есть одна проблема с импульсом: когда мы очень близки к цели, наш импульс в большинстве случаев очень велик, и он не знает, что он должен замедлиться. Это может вызвать его пропуск или колебание вокруг минимумов.
  • Ускоренный градиент нестеров преодолевает эту проблему, начав рано тормозить. В импульсе мы сначала вычисляем градиент, а затем совершаем скачок в этом направлении, усиленный тем импульсом, который у нас был ранее. NAG делает то же самое, но в другом порядке: сначала мы делаем большой скачок, основываясь на нашей хранимой информации, а затем вычисляем градиент и делаем небольшую коррекцию. Это, казалось бы, несущественное изменение дает значительные практические ускорения.
  • AdaGrad или адаптивный градиент позволяет адаптировать скорость обучения на основе параметров. Он выполняет большие обновления для нечастых параметров и меньшие обновления для частых. Из-за этого он хорошо подходит для разреженных данных (НЛП или распознавания изображений). Другое преимущество состоит в том, что это в основном устраняет необходимость настройки скорости обучения. Каждый параметр имеет собственную скорость обучения, и из-за особенностей алгоритма скорость обучения монотонно уменьшается. Это вызывает самую большую проблему: в какой-то момент скорость обучения настолько мала, что система прекращает обучение.
  • AdaDelta решает проблему монотонно снижающейся скорости обучения в AdaGrad. В AdaGrad скорость обучения была рассчитана приблизительно как единица, разделенная на сумму квадратных корней. На каждом этапе вы добавляете еще один квадратный корень к сумме, что приводит к постоянному увеличению знаменателя. В AdaDelta вместо суммирования всех прошлых квадратных корней используется скользящее окно, которое позволяет уменьшать сумму. RMSprop очень похож на AdaDelta
  • Адам или адаптивный импульс - это алгоритм, похожий на AdaDelta. Но в дополнение к сохранению скорости обучения для каждого из параметров он также сохраняет изменения импульса для каждого из них в отдельности.

    Несколько визуализаций: enter image description hereenter image description here

Я бы сказал, что СГД, Моментум и Нестеров уступают последним 3.

Ответ 2

Ответ Сальвадора Дали уже объясняет различия между некоторыми популярными методами (например, оптимизаторами), но я постараюсь подробнее остановиться на них.
(Обратите внимание, что наши ответы не совпадают по некоторым вопросам, особенно в отношении ADAGRAD.)

Классический импульс (CM) против ускоренного градиента Nesterov (NAG)

(В основном на основе раздела 2 в статье " О важности инициализации и импульса в глубоком обучении".)

Каждый шаг в CM и NAG фактически состоит из двух подэтапов:

  • [0.9,1) импульса - это просто часть (обычно в диапазоне [0.9,1)) последнего шага.
  • Зависимый от градиента подэтап - это похоже на обычный шаг в SGD - он является произведением скорости обучения и вектора, противоположного градиенту, в то время как градиент вычисляется с того места, откуда начинается этот подэтап.

CM сначала выполняет подэтап градиента, а NAG сначала выполняет подэтап импульса.

Вот демонстрация ответа об интуиции для CM и NAG:

CM vs NAG example

Так что NAG кажется лучше (по крайней мере на картинке), но почему?

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

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

"После" кажется правильным ответом, как правило, градиент в некоторой точке θ приблизительно указывает вам направление в направлении от θ до минимума (с относительно правильной величиной), в то время как градиент в какой-то другой точке с меньшей вероятностью будет указывать Вы в направлении от θ до минимума (с относительно правильной величиной).

Вот демонстрация (из рисунка ниже):

CM vs NAG in a specific moment in the awesome gif

  • Минимум - это то, где находится звезда, а кривые - это контурные линии. (Для объяснения о контурных линиях и почему они перпендикулярны градиенту, смотрите видео 1 и 2 легендарной 3Blue1Brown.)
  • (Длинная) фиолетовая стрелка является подэтапом импульса.
  • Прозрачная красная стрелка является подэтапом градиента, если он начинается до подэтапа импульса.
  • Черная стрелка является подэтапом градиента, если он начинается после подэтапа импульса.
  • КМ попадет в цель темно-красной стрелки.
  • NAG попадет в цель черной стрелки.

Обратите внимание, что этот аргумент о том, почему NAG лучше, не зависит от того, близок ли алгоритм к минимуму.
В целом, как NAG, так и CM часто сталкиваются с проблемой накопления большего количества импульса, чем им полезно, поэтому всякий раз, когда им приходится менять направление, у них возникает неловкое "время отклика". Преимущество NAG перед CM, которое мы объяснили, не предотвращает проблему, а только делает "время отклика" NAG менее неловким (но все же неловким).

Эта проблема "времени отклика" прекрасно продемонстрирована в гифке Алеком Рэдфордом (который появился в ответе Сальвадора Дали):
An example of the embarrassing response time of both momentum methods

ADAGRAD

(Главным образом основанный на разделе 2.2.2 в ADADELTA: Метод адаптивной скорости обучения (оригинальная статья ADADELTA), поскольку я нахожу его гораздо более доступным, чем Адаптивные методы субградиента для онлайн-обучения и стохастической оптимизации (оригинальная статья ADAGRAD).)

В SGD шаг задается как - learning_rate * gradient, тогда как learning_rate является гиперпараметром.
ADAGRAD также имеет гиперпараметр learning_rate, но фактическая скорость обучения для каждого компонента градиента рассчитывается индивидуально.
Компонент i -th шага t -th определяется как:

              learning_rate 
- --------------------------------------- * gradient_i_t
  norm((gradient_i_1, ..., gradient_i_t))

в то время как:

  • gradient_i_k - это компонент i -th градиента на шаге k -th
  • (gradient_i_1,..., gradient_i_t) - это вектор с t компонентами. Это не интуитивно понятно (по крайней мере для меня), что построение такого вектора имеет смысл, а то, что делает алгоритм (концептуально).
  • norm(vector) - это евклидова норма (также известная как l2 норма) vector, которая является нашим интуитивным понятием длины vector.
  • Смущает то, что в ADAGRAD (как и в некоторых других методах) выражение, умноженное на gradient_i_t (в данном случае learning_rate/norm(...)), часто называют "скоростью обучения" (на самом деле я назвал ее " фактическая скорость обучения "в предыдущем пункте). Я думаю, это потому, что в SGD гиперпараметр learning_rate и это выражение - одно и то же.
  • В реальной реализации некоторая константа будет добавлена к знаменателю, чтобы предотвратить деление на ноль.

Например, если:

  • Компонент i -th градиента на первом этапе равен 1.15
  • Компонент i -th градиента на втором этапе равен 1.35
  • Компонент i -th градиента на третьем этапе равен 0.9

Тогда норма (1.15, 1.35, 0.9) - это длина желтой линии, которая равна:
sqrt(1.15^2 + 1.35^2 + 0.9^2) = 1.989.
И поэтому i -th компонент третьего шага: - learning_rate/1.989 * 0.9

l2 norm example

Обратите внимание на две вещи о компоненте i -th этого шага:

  1. Это пропорционально learning_rate.
  2. При его расчете норма увеличивается, и, следовательно, скорость обучения уменьшается.

Это означает, что ADAGRAD чувствителен к выбору гиперпараметра learning_rate.
Кроме того, может случиться так, что через некоторое время шаги станут настолько маленькими, что ADAGRAD фактически застрянет.

ADADELTA и RMSProp

Из бумаги ADADELTA:

Идея, представленная в этом документе, была получена из ADAGRAD, чтобы улучшить два основных недостатка метода: 1) постоянное снижение скорости обучения в течение обучения и 2) необходимость вручную выбранной глобальной скорости обучения.

Затем в документе объясняется улучшение, которое призвано устранить первый недостаток:

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

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

Это приближение окна размера w потому что веса на предыдущих этапах очень малы.

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

a comet's trail as an intuition for a moving average)

Если вы сделаете только это изменение в ADAGRAD, вы получите RMSProp, который был предложен Джеффом Хинтоном в лекции 6e его курса Coursera.

Таким образом, в RMSProp компонент i -th шага t -th определяется как:

                   learning_rate
- ------------------------------------------------ * gradient_i_t
  sqrt(exp_decay_avg_of_squared_grads_i + epsilon)

в то время как:

  • epsilon - это гиперпараметр, который предотвращает деление на ноль.
  • exp_decay_avg_of_squared_grads_i является экспоненциально убывающим средним квадратов i -th компонентов всех вычисленных градиентов (включая gradient_i_t).

Но, как уже упоминалось, ADADELTA также стремится избавиться от гиперпараметра learning_rate, поэтому в нем должно быть больше вещей.

В ADADELTA компонент i -th шага t -th определяется как:

  sqrt(exp_decay_avg_of_squared_steps_i + epsilon)
- ------------------------------------------------ * gradient_i_t
  sqrt(exp_decay_avg_of_squared_grads_i + epsilon) 

в то время как exp_decay_avg_of_squared_steps_i является экспоненциально убывающим средним квадратов i -th компонентов всех вычисленных шагов (до шага t-1 -th).
sqrt(exp_decay_avg_of_squared_steps_i + epsilon) в некоторой степени похож на импульс, и, согласно статье, он "выступает в качестве члена ускорения". (В документе также приводится еще одна причина, по которой он был добавлен, но мой ответ уже слишком длинный, поэтому, если вам интересно, ознакомьтесь с разделом 3.2.)

Адам

(В основном на основе Адама: метод стохастической оптимизации, оригинальная статья Адама.)

Адам короток для Адаптивной Оценки Момента (см. Этот ответ для объяснения об имени).
Компонент i -th шага t -th определяется как:

                   learning_rate
- ------------------------------------------------ * exp_decay_avg_of_grads_i
  sqrt(exp_decay_avg_of_squared_grads_i) + epsilon

в то время как:

  • exp_decay_avg_of_grads_i - экспоненциально exp_decay_avg_of_grads_i среднее значение i -th компонентов всех вычисленных градиентов (включая gradient_i_t).
  • На самом деле, и exp_decay_avg_of_grads_i и exp_decay_avg_of_squared_grads_i также исправлены, чтобы учесть смещение к 0 (подробнее об этом см. Раздел 3 в статье, а также ответ в stats.stackexchange).

Обратите внимание, что Адам использует экспоненциально убывающее среднее из компонентов i -th градиентов, где большинство методов SGD используют компонент i -th текущего градиента. Это приводит к тому, что Адам ведет себя как "тяжелый шар с трением", как объясняется в статье " GAN, обученные правилом обновления двух временных масштабов, сходятся к локальному равновесию Нэша".
Посмотрите этот ответ для получения дополнительной информации о том, как поведение Адама, подобное импульсу, отличается от обычного поведения, напоминающего импульс.

Ответ 3

Позвольте свести это к паре простых вопросов:

Какой оптимизатор даст мне лучший результат/точность?

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

Какой оптимизатор я должен использовать прямо сейчас?

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

Длинная история

Есть несколько аспектов, которые следует учитывать при выборе оптимизатора:

  • Простота использования (т.е. как быстро вы можете найти параметры, которые работают для вас);
  • Скорость сходимости (базовая, как SGD или выше, чем любая другая);
  • Объем памяти (обычно от 0 до x2 размера вашей модели);
  • Отношение к другим частям учебного процесса.

Простой SGD - это минимум, который можно сделать: он просто умножает градиенты на скорость обучения и добавляет результат к весам. SGD обладает рядом прекрасных качеств: у него всего 1 гиперпараметр; не требует дополнительной памяти; это оказывает минимальное влияние на другие части обучения. Он также имеет 2 недостатка: он может быть слишком чувствительным к выбору скорости обучения, а обучение может занять больше времени, чем при использовании других методов.

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

Затраты памяти, как правило, незначительны и могут быть проигнорированы. Если модель не очень большая, или вы тренируетесь на GTX760, или боретесь за лидерство ImageNet. Более простые методы, такие как импульс или ускоренный градиент Нестерова, требуют 1,0 или менее размера модели (размер гиперпараметров модели). Методы второго порядка (Адам, возможно, потребуют вдвое больше памяти и вычислений).

Скорость сходимости -wise почти во всех отношениях лучше, чем в SGD, и что-либо еще трудно сравнивать. Одно замечание может заключаться в том, что AdamOptimizer способен начать тренировку практически сразу, без разминки.

Я считаю, что удобство использования является наиболее важным при выборе оптимизатора. Разные оптимизаторы имеют разное количество гиперпараметров и имеют разную чувствительность к ним. Я считаю Адама самым простым из всех доступных. Обычно вам нужно проверить 2-4 learning_rate между 0.001 и 0.0001 чтобы выяснить, хорошо ли сходится модель. Для сравнения для SGD (и импульса) я обычно стараюсь [0.1, 0.01,... 10e-5]. У Адама есть еще 2 гиперпараметра, которые редко нужно менять.

Связь между оптимизатором и другими частями обучения. Настройка гиперпараметра обычно включает одновременный выбор {learning_rate, weight_decay, batch_size, droupout_rate}. Все они взаимосвязаны, и каждый может рассматриваться как форма регуляризации модели. Например, нужно обратить пристальное внимание, если точно используется weight_decay или L2-norm, и, возможно, выбрать AdamWOptimizer вместо AdamOptimizer.