Оптимизация

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

AdaGrad, RMSProp, Adam, AdamW — свой масштаб шага для каждой координаты

Шаг 68 из 117 · ~32 мин

Идея

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

xk+1=xkαE[g2]+εgkx_{k+1} = x_k - \frac{\alpha}{\htmlData{k=scale}{\sqrt{\mathbb{E}[g^2]} + \varepsilon}} \odot g_k

Обратите внимание, что берётся из вторых моментов градиента, а не из кривизны. Это не одно и то же, и связь между ними эвристическая — что и объясняет, почему адаптивные методы работают хорошо, но без гарантий.

Три поколения

AdaGrad накапливает все квадраты градиентов: sk=sk1+gk2s_k = s_{k-1} + g_k^2, шаг α/sk\alpha / \sqrt{s_k}.

Проблема видна сразу: знаменатель только растёт, значит шаг только убывает. При постоянном g=1|g| = 1:

шаговнакопительшаг при α=0.1\alpha = 0.1
11110.10.1
1001001001000.010.01
10410^410410^40.0010.001

Шаг падает как 1/t1/\sqrt{t} и в итоге останавливает обучение независимо от того, сошлось оно или нет. Для выпуклых задач это даже правильно (условия Роббинса–Монро), для глубоких сетей — фатально.

RMSProp заменяет сумму на экспоненциальное среднее: vk=β2vk1+(1β2)gk2v_k = \beta_2 v_{k-1} + (1-\beta_2) g_k^2. Теперь знаменатель выходит на стационарный уровень:

шаговvvшаг
110.0010.0013.163.16
1001000.09520.09520.3240.324
10410^40.999960.999960.10.1

Шаг больше не вырождается — он оседает на α\alpha. Но посмотрите на первую строку: на старте шаг в тридцать раз больше заданного, потому что vv начинается с нуля и ещё не успел накопиться. Это и есть проблема, которую решает следующий метод.

Adam = RMSProp + момент + коррекция смещения.

mk=β1mk1+(1β1)gk,vk=β2vk1+(1β2)gk2m_k = \beta_1 m_{k-1} + (1-\beta_1)g_k, \qquad v_k = \beta_2 v_{k-1} + (1-\beta_2)g_k^2

m^k=mk1β1k,v^k=vk1β2k,xk+1=xkαm^kv^k+ε\hat{m}_k = \frac{m_k}{1 - \beta_1^k}, \qquad \hat{v}_k = \frac{v_k}{1 - \beta_2^k}, \qquad x_{k+1} = x_k - \frac{\alpha \hat{m}_k}{\sqrt{\hat{v}_k} + \varepsilon}

Зачем коррекция смещения

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

kkсырое mkm_kдоля от ggпосле коррекции
110.10.110%10\%1.01.0
220.190.1919%19\%1.01.0
550.410.4141%41\%1.01.0

Делители 1β1k1 - \beta_1^k и 1β2k1 - \beta_2^k ровно компенсируют недобор. Результат проверяется точно: при постоянном градиенте шаг Adam равен α\alpha с первой же итерации и остаётся таким при k=100k = 100. Без коррекции первые шаги были бы либо в десять раз меньше (по mm), либо в тридцать раз больше (по vv) — и они не компенсируют друг друга.

Что даёт масштабная инвариантность

Ключевое свойство: величина шага почти не зависит от масштаба градиента. Проверим, меняя градиент на пять порядков (при α=0.001\alpha = 0.001, из нулевого состояния):

ggшаг/α\lvert\text{шаг}\rvert / \alpha
1001001.00000001.0000000
110.99999990.9999999
10310^{-3}0.99999000.9999900
10710^{-7}0.90909090.9090909

Первые три строки — та самая инвариантность: умножьте лосс на тысячу, и Adam почти не заметит. Ради этого его и берут для задач с разномасштабными параметрами (эмбеддинги против bias’ов).

Последняя строка — предел, о котором редко говорят. При gεg \sim \varepsilon слагаемое ε=108\varepsilon = 10^{-8} перестаёт быть пренебрежимым, и инвариантность ломается: шаг падает на 9%9\%. То есть ε\varepsilon — не только «защита от деления на нуль», но и порог, ниже которого Adam ведёт себя как обычный SGD. На затухших градиентах это имеет значение.

AdamW: L2 внутри градиента — не то же самое

Тонкость, которая стоила сообществу нескольких лет плохих результатов.

подходчто делает
L2 в лоссе (Adam)gg+λwg \leftarrow g + \lambda w, затем всё делится на v^\sqrt{\hat v}
decoupled (AdamW)wwαm^/(v^+ε)αλww \leftarrow w - \alpha \hat m / (\sqrt{\hat v} + \varepsilon) - \alpha\lambda w

В первом случае штраф проходит через адаптивный знаменатель, значит его сила зависит от масштаба градиентов. Проверим на игрушечной задаче с λ=0.01\lambda = 0.01, меняя величину градиента лосса:

градиент лоссаAdam: wwAdamW: ww
1118.16-18.1617.32-17.32
0.010.011.00-1.0017.32-17.32
10010018.99-18.9917.32-17.32

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

Отсюда практический вывод: у Adam «weight decay» и «L2-регуляризация» — разные вещи, а у SGD они совпадают. Поэтому torch.optim.AdamW существует отдельно, и переносить λ\lambda между SGD и Adam нельзя.

Когда адаптивность не помогает

Сравните Adam с моментом на двух ландшафтах виджета.

лосс, логарифмическая шкала

шаг α 0.1
итераций 120
f в конце
4.58e+13
обусловленность κ
100
порог 2/L
0.02
 
разошлось

Порог 2/L относится к обычному спуску. У Adam эффективный шаг нормирован, поэтому он выдерживает α, при котором спуск давно разошёлся бы.

Здесь Adam в своей стихии: кривизна диагональна, и диагональный масштаб выпрямляет ландшафт почти полностью. Обратите внимание, что шаг 0.1 для него безопасен, хотя для спуска порог всего 0.02.

Второй ландшафт — тот же спектр, тот же κ\kappa, повёрнутый на 45°45°. Adam теряет почти всё преимущество, потому что диагональ не видит поворота. Это фундаментальное ограничение: адаптивные методы приближают гессиан диагональной матрицей, и когда кривизна «наклонена», приближение плохое.

Прочие известные ограничения:

  • обобщение. SGD с моментом часто даёт лучший тест при том же обучающем лоссе, особенно в свёрточных сетях. Причина обсуждается до сих пор;
  • сходимость не гарантирована. У исходного доказательства Adam нашли ошибку; существуют выпуклые задачи, где он не сходится (отсюда AMSGrad);
  • память. Два накопителя на параметр — то есть в три раза больше состояния, чем у SGD. Для больших моделей это существенная часть бюджета памяти.

Практика сегодня примерно такая: трансформеры и языковые модели — AdamW почти всегда, свёрточные сети — часто SGD с моментом, и обе привычки имеют эмпирические, а не теоретические основания.

Источники

Проверки

0 из 2
  1. Адаптивные методы и их пределы

    Отметьте все верные утверждения об AdaGrad, RMSProp, Adam и AdamW.

  2. Один шаг Adam

    Реализуйте adam_step(g, m, v, t, lr) — один шаг Adam для одного параметра. Константы фиксированы: β1=0.9\beta_1 = 0.9, β2=0.999\beta_2 = 0.999, ε=108\varepsilon = 10^{-8}.

    Верните [m_new, v_new, m_hat, v_hat, step]:

    m=β1m+(1β1)g,v=β2v+(1β2)g2m' = \beta_1 m + (1-\beta_1) g, \qquad v' = \beta_2 v + (1-\beta_2) g^2

    m^=m1β1t,v^=v1β2t,step=αm^v^+ε\hat m = \frac{m'}{1 - \beta_1^{\,t}}, \qquad \hat v = \frac{v'}{1 - \beta_2^{\,t}}, \qquad \text{step} = \frac{\alpha\,\hat m}{\sqrt{\hat v} + \varepsilon}

    step — величина, которую вычитают из параметра, со знаком.

    Проверить себя проще всего первым случаем: из нулевого состояния при любом ненулевом градиенте step обязан оказаться практически равен lr. Если у вас там 0.1lr0.1 \cdot lr — забыта коррекция m^\hat m; если 31lr31 \cdot lr — забыта коррекция v^\hat v.

    функция adam_step

    Загрузка редактора…

    Ctrl/⌘ + Enter