Заметки DL Продвинутый градиентный спуск

Продвинутый градиентный спуск Заметки DL

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

Фото Jack Anstey / Unsplash

В моей предыдущей статье о градиентном спуске я объяснил основные концепции и основные проблемы этого вида оптимизации.

Однако я рассмотрел только Стохастический Градиентный Спуск (SGD) и реализацию градиентного спуска с помощью методов “batch” и “mini-batch”.

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

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

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

Сравнение алгоритмов с использованием простой целевой функции

На протяжении этой статьи я покажу, как я реализовал разные алгоритмы на Python.

Я создал Jupyter Notebook, который вы можете найти на GitHub или открыть на Google Colab, чтобы увидеть весь использованный код для создания показанных здесь изображений.

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

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

import numpy as np# Создание функции для вычисления поверхностидеф f(theta):  x = theta[0]  y = theta[1]  return x**2 - y**2# Определение функции для вычисления градиентаdef grad_f(theta):    returnValue = np.array([0.,0.])    x = theta[0]    y = theta[1]    returnValue[0] += 2*x    returnValue[1] += - 2*y    return returnValue

Импульс

Фото Sharon Pittaway на Unsplash

Мы можем сравнить алгоритм оптимизации с шаром, скатывающимся вниз.

Если бы у “шара” был импульс, как у него есть в реальной жизни, то после ускорения вниз с полной скоростью он был бы менее склонен застревать в локальном минимуме.

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

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

Переводный импульс.

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

Гравитационная потенциальная энергия.

Более того, существует прямая связь между потенциальной энергией объекта и приложенной к нему силой

Сила равна отрицательному градиенту потенциальной энергии.

Связь между p и U может быть выведена из второго закона Ньютона о движении:

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

Второй закон Ньютона о движении.

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

Как добавить импульс?

При инициализации алгоритма оптимизации мы помещаем “шар” на высоту h, придавая ему потенциальную энергию U.

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

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

Обновление импульса.

Из-за терма скорости “частица” набирает скорость в любом направлении с постоянным градиентом.

Я реализовал это в виде функции на Python, следующим образом:

def gradient_descent(x_init, y_init, step_size, n_iters, momentum):  eta = step_size  mu = momentum  # Обратите внимание, что при mu = 0 данный алгоритм сводится к стохастическому градиентному спуску  # Инициализация массивов для хранения результатов  theta = np.tile([x_init, y_init], (n_iters,1) )  z = np.tile([f(theta[0])], n_iters )  # Инициализация импульса  v_t = np.array([0,0])  for k in range (1, n_iters):      # Обновление импульса      v_t = mu*v_t - eta*grad_f(theta[k-1])   # Обновление положения      theta[k] = theta[k-1] + v_t      z[k] = f(theta[k])  # Хранение координат положения  dataset = np.stack((theta[:,0], theta[:,1], z), 1)    return dataset

Импульсное обновление как ускоряет оптимизацию в направлениях с низкой кривизной, так и сглаживает (смягчает) колебания, вызванные “ландшафтными” особенностями или зашумленными данными [3].

Некоторые утверждают, что обновление со скоростью Momentum на самом деле более согласовано с физическим эффектом коэффициента трения, поскольку оно уменьшает кинетическую энергию системы [2].

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

Будучи меньшим 1, параметр импульса действует как экспоненциально взвешенная сумма предыдущих градиентов, и обновление скорости можно переписать как [3][5]:

 Скорость переписывается как взвешенная сумма.

где g – мгновенный градиент, а v – сглаженная оценка градиента.

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

Обычно он равен 0.9, но иногда он “планируется”, т.е. увеличивается от 0.5 до 0.99 по мере продвижения итераций.

Ускоренный градиент Нестерова (NAG)

Предложено Нестеровым, Й. в 1983 году.

Обновление Нестерова внедряет функцию “предпросмотра”, чтобы улучшить стабильность и скорость сходимости импульса для выпуклых функций.

Обновление NAG.

Если Momentum использует текущую позицию для обновления градиента, то NAG сначала выполняет частичное обновление текущей позиции, зная, что

Понимание обновления предпросмотра.
Векторное представление обновлений Momentum и NAG.

Чтобы внедрить это как функцию Python, я просто внес следующую модификацию в “обновление скорости” в коде, который я показал ранее:

# Обновление скорости# Momentumv_t = mu*v_t - eta *grad_f(theta[k-1])# NAGv_t = mu*v_t - eta *grad_f(theta[k-1] + mu * v_t)

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

Разница заметна на следующей фигуре.

Сравнение оптимизаций спуска Momentum и NAG для сложной поверхности.

Оба оптимизатора инициализируются в одних и тех же координатах и используют одинаковый параметр импульса (0.95, фиксированный).

Следующая анимация также помогает увидеть интуицию, стоящую за планированием или “затуханием” параметра импульса.

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

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

Адаптивные методы

Другие алгоритмы оптимизации, показанные на анимации выше, являются адаптивными методами, которые я опишу в этом разделе.

При просмотре этого простого примера с локальным и глобальным минимумом, Momentum и NAG могут казаться намного лучше, чем остальные методы. Однако адаптивные алгоритмы более устойчивы. Я покажу это на практическом примере в другой статье.

Адаптивный градиентный алгоритм (AdaGrad)

AdaGrad – это семейство субградиентных алгоритмов для стохастической оптимизации, представленных Джоном Дучи, Эладом Хазаном и Ёрамом Сингером в 2011 году.

Они предложили улучшить градиентное обучение, включив историю градиентов в каждое новое обновление весов.

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

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

Для этого последовательность оценок градиента хранится следующим образом:

Сумма квадратов градиентов или внешнее произведение истории градиентов.

Если мы оптимизируем функцию с n координатами или параметрами, g будет вектором с n элементами, и то же самое будет с G.

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

Обновление AdaGrad.

Параметр ε используется для избежания деления на ноль и обычно принимает небольшое значение, например, 1e-08.

Интересно, что определение G похоже на нецентрированную (с нулевым средним) дисперсию распределения градиентов.

Определение дисперсии.

Дисперсия – это мера энергии распределения.

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

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

AdaGrad также автоматически реализует уменьшение скорости обучения на основе времени (накопления предыдущих градиентов) и кривизны целевой функции (“области” с меньшей дисперсией градиента получат меньшие шаги). Это улучшает скорость сходимости алгоритма.

Я реализовал AdaGrad в виде функции на Python следующим образом:

def Adagrad(x_init, y_init, step_size, n_iters):  eta = step_size  G_t = 0  eps = 1e-8  theta = np.tile([x_init, y_init], (n_iters,1) )  z = np.tile([f(theta[0])], n_iters )  for k in range (1, n_iters):      # Вычисление градиента      g_t = grad_f(theta[k-1])      # Накопление квадратов градиентов      G_t += g_t**2            # Обновление позиции      theta[k] = theta[k-1] - eta * g_t / (np.sqrt(G_t) + eps)      z[k] = f(theta[k])  # Сохранение координат позиции  dataSet = np.stack((theta[:,0], theta[:,1], z), 1)  return dataSet

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

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

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

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

Метод Root Mean Square Propagation (RMSProp)

Неопубликованный метод, но упоминается в слайдах лекции 6 курса “Нейронные сети для машинного обучения” от профессора Джеффри Хинтон.

Концепция этого алгоритма аналогична методу момента. Он также использует последнюю историю изменения величин градиентов для обновления весов.

Однако, аналогично AdaGrad, RMSProp изменяет скорость обучения, а не градиент.

Для этого скорость обучения делится на среднеквадратичное значение недавних градиентов.

Сначала алгоритм вычисляет взвешенную сумму квадратов значений функции стоимости и предыдущих значений:

Экспоненциально взвешенная сумма квадратов стоимостей.

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

Это аналогично переписанной форме метода момента, о которой я упоминал ранее, но примененной к квадратам стоимостей, а не к градиенту.

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

Правило обновления RMSProp.

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

Обратите внимание, что вычисление корня из взвешенной суммы (или взвешенного среднего) квадратов равносильно вычислению среднеквадратичного значения (Root Mean Square — RMS) этих значений.

Определение RMS.

RMS сигнала является представлением его общей энергии (в отличие от дисперсии, которая представляет энергию его распределения)[1].

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

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

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

Вот как я кодировал это в виде функции на Python:

def RMSProp(x_init, y_init, step_size, n_iters, decay):  beta = decay # 0.8, 0.9, ..., 0.99  eta = step_size  eps = 1e-8  MSQ = 0  theta = np.tile([x_init, y_init], (n_iters,1) )  z = np.tile([f(theta[0])], n_iters )  for k in range (1, n_iters):      # Вычисление градиента      g_t = grad_f(theta[k-1])      # Вычисление взвешенного среднего квадратов значений      MSQ = beta * MSQ + (1 - beta) * g_t**2            # Обновление позиции (деление eta на RMS)      theta[k] = theta[k-1] - eta * g_t / (np.sqrt(MSQ) + eps)      z[k] = f(theta[k])  # Запись координат позиции  dataSet = np.stack((theta[:,0], theta[:,1], z), 1)  return dataSet

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

Фото от Gonzalo Kaplanski на Unsplash

AdaDelta

Предложен Мэтью Зайлером в 2012 году.

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

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

На практике это означает деление скорости обучения на RMS предыдущих градиентов в определенном окне, аналогично как это делает RMSprop:

Пример масштабирования скорости обучения, аналогичного RMSProp.

Следующая модификация от AdaGrad – это коррекция единиц оптимизационных обновлений.

В AdaGrad (и всех других оптимизационных алгоритмах, о которых я рассказывал до этого), единицы оптимизационных шагов не соответствуют единицам параметров, которые мы изменяем для оптимизации функции стоимости [9]:

Мы знаем со школы, что нельзя складывать яблоки и апельсины. Но с помощью этих оптимизационных алгоритмов это как будто мы складываем “яблоки” (текущие значения параметров, θₜ и некоторую неизвестную величину (оптимизационный шаг Δθ), которые математически можно сложить с ними, чтобы получить новые “яблоки” (обновленные параметры, θₜ ₊₁. Это просто работает, но не имеет смысла в реальной жизни.

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

Сравнивая это наблюдение с правилом обновления, аналогичным RMSProp, Зайлер определил правильную форму термина обновления для сохранения правильных единиц.

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

Шаг AdaDelta для обновления параметра.

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

Алгоритм выглядит следующим образом, если мы реализуем его в виде функции на Python:

def AdaDelta(x_init, y_init, step_size, n_iters, decay):    eta = step_size  G_t = 0  eps = 1e-8  E_gsq = 0  E_xsq = 0  theta = np.tile([x_init, y_init], (n_iters,1) )  z = np.tile([f(theta[0])], n_iters )  for k in range (1, n_iters):      g_t = grad_f(theta[k-1])      E_gsq = decay * E_gsq + (1 - decay) * g_t**2      delta = - np.sqrt(E_xsq + eps) / np.sqrt(E_gsq + eps) * g_t      E_xsq = decay * E_xsq + (1 - decay) * delta**2      theta[k] = theta[k-1] + delta      z[k] = f(theta[k])  # Настройка набора данных для анимации  dataSet = np.stack((theta[:,0], theta[:,1], z), 1)  # Комбинирование координат позиции  return dataSet

AdaDelta объединяет преимущества методов оптимизации, на основе которых он создан.

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

Знаменатель обеспечивает точность AdaGrad по каждому измерению, но без избыточного затухания скорости обучения (точно как RMSProp).

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

Adam (Адаптивный Момент)

Это один из самых популярных алгоритмов сегодня.

Он был представлен Diederik P. Kingma и Jimmy Lei Ba в 2014 и стал очень популярным из-за своей вычислительной эффективности и хорошего функционирования на проблемах с большим количеством данных и параметров.

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

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

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

Экспоненциальное скользящее среднее градиентов стоимости.

Затем есть термин от RMSprop, экспоненциального скользящего среднего квадратов градиентов.

Экспоненциальное скользящее среднее квадратов градиентов стоимости.

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

Правило обновления Adam.

Значения с тильдой (~) соответствуют коэффициентам коррекции смещения, которые вводятся для уменьшения вклада начальных значений m и v по мере продвижения обучения:

Коэффициенты коррекции начального смещения для Adam.

t = текущая эпоха обучения.

В отличие от AdaDelta, Adam требует настройки некоторых гиперпараметров, но их легко интерпретировать.

Термины β₁ и β₂ – это коэффициенты затухания экспоненциального скользящего среднего градиентов и квадратов градиентов соответственно.

Большие значения присваивают больший вес предыдущим градиентам, что обеспечивает более плавное поведение и меньшую реакцию на недавние изменения. Значения, близкие к нулю, уделяют больше внимания недавним изменениям в градиентах. Типичные значения для β₁ = 0.9 и β₂ = 0.999.

ε, как и во всех предыдущих случаях, – это постоянная, добавляемая для избежания деления на ноль, обычно установленная на 1e-8.

Несмотря на наличие ряда дополнительных терминов и значительные преимущества, Adam легко реализовать:

def Adam(x_init, y_init, step_size, n_iters,          beta_1 = 0.9, beta_2 = 0.999):  eps = 1e-8  eta = step_size  # Инициализируем вектора  m_t = np.array([0,0])  v_t = np.array([0,0])  theta = np.tile([x_init, y_init], (n_iters,1) )  z = np.tile([f(theta[0])], n_iters )  for k in range (1, n_iters):      # Вычисляем градиент      g_t = grad_f(theta[k-1])            # Вычисляем "аналог момента" (взвешенное среднее)      m_t = beta_1 * m_t + (1 - beta_1)*g_t      # Вычисляем среднее значение квадратов градиентов      v_t = beta_2 * v_t + (1 - beta_2)*g_t**2            # Коэффициенты коррекции начального смещения      m_t_hat = m_t/(1 - beta_1**k)      v_t_hat = v_t/(1 - beta_2**k)      # Обновляем положение с учетом скорректированного градиента и скорости обучения      theta[k] = theta[k-1] - eta * m_t_hat/(np.sqrt(v_t_hat)+ eps)      z[k] = f(theta[k])  # Сохраняем координаты положения  dataSet = np.stack((theta[:,0], theta[:,1], z), 1)   return dataSet

Интересно, авторы статьи отмечают, что термин

Масштабирование скорости обучения Adam

похож на определение отношения сигнал-шум (SNR):

Отношение сигнал-шум

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

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

Производительность для разных скоростей обучения

Я решил сравнить, как разные оптимизаторы проявляют себя при инициализации с разными “глобальными” скоростями обучения.

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

Сравнение эволюции координат x и y во время оптимизации с помощью различных алгоритмов. Для Momentum и NAG mu = 0.95. Для RMSProp и AdaDelta параметр затухания = 0.9.

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

Для малых скоростей обучения ясно, что Adam и RMSProp похожи и превосходят Momentum и SGD.

Однако при больших скоростях обучения RMSProp показывает стабильные осцилляции вокруг оптимального значения x (x = 0), в то время как Adam стабилизируется после начального переходного процесса, благодаря смягчающему эффекту члена импульса в числителе.

Адаптивные алгоритмы отличаются симметрией раньше, чем методы SGD и Momentum, за исключением случая с глобальной скоростью обучения 0.1, где Momentum и NAG превосходят AdaDelta.

Опять же, эти наблюдения относятся только к этому конкретному сценарию.

Выводы

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

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

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

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

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

Дальнейшее чтение

Ссылки

Все иллюстрации, если не указано иное, созданы Автором.

[1] Онлайн-курс Глубокое понимание глубокого обучения от Майка Коэна ( sincxpress.com)

[2] Онлайн-курс Стэндфорд: CS231 Сверточные нейронные сети для визуального распознавания

[3] Го Х. “Почему на самом деле работает импульс”, Distill, 2017. http://doi.org/10.23915/distill.00006

[4] Виллаларга, Д. ” AdaGrad “. Опубликовано в Cornell University Computational Optimization Open Textbook — Optimization Wiki.

[5] Бенджио, Йошуа. “Практические рекомендации по обучению глубоких архитектур на основе градиентного подхода.” Нейронные сети: секреты и приемы: Второе издание. Берлин, Гейдельберг: Springer Berlin Heidelberg, 437–478, 2012. Веб-сайт: arXiv:1206.5533 [cs.LG]

[6] Сутскевер, И., Мартенс, Д., Даль, Г. & Хинтон, Г. “О важности инициализации и импульса в глубоком обучении”. Материалы конференции по машинному обучению, 28(3):1139–1147, 2013. Доступно по ссылке https://proceedings.mlr.press/v28/sutskever13.html.

[7] Дучи, Д., Хазан, Э., Сингер, Й., “Адаптивные методы субградиента для онлайн-обучения и стохастической оптимизации”. Журнал машинного обучения, 12(61):2121−2159, 2011. Доступно по ссылке: https://jmlr.org/papers/v12/duchi11a.html

[8] Джейсон Браунли, Градиентный спуск с AdaGrad с нуля. 2021

[9] Зейлер, М. “ADADELTA: МЕТОД АДАПТИВНОЙ СКОРОСТИ ОБУЧЕНИЯ”, 2012. arXiv:1212.5701v1 [cs.LG]

[10] Кингма, Д., Ба, Дж. “Адам: Метод стохастической оптимизации”, 2014. arXiv:1412.6980 [cs.LG]

Опубликовано на https://www.makerluis.com 5 декабря 2023 года.