Почему самый быстрый старт не гарантирует лучший финиш?
Оптимизатор не меняет, где расположены минимумы функции потерь, но меняет
траекторию, скорость и часто то, к какому из многих решений придёт обучение.
История градиентов может задавать инерцию или отдельный масштаб каждой
координаты — и одна и та же задача решается то за сотню шагов, то не решается
вовсе.
Ландшафт один, походка разная
В уроке 22 мы условились: антиградиент указывает направление
самого быстрого локального убывания. Из этого не следует, что идти надо именно
туда. Направление наибыстрейшего спуска — свойство одного шага; нам же нужен
маршрут из десятков тысяч шагов, и жадность на каждом из них не гарантирует
короткого пути.
Оптимизатор — это правило, по которому история наблюдённых градиентов
превращается в очередной сдвиг весов:
θt+1=θt−ηDt(g1,…,gt).
Обычный градиентный спуск — частный случай с самой короткой памятью:
Dt=gt.
Все методы этого урока отличаются только видом Dt. Минимумы функции потерь
от выбора Dt не сдвигаются ни на волос: они заданы данными и моделью.
Меняется путь, скорость и — что важнее всего в переопределённой области из
урока 59 — то, какой именно из множества почти одинаково хороших
минимумов будет найден.
Шарик в узком овраге
Возьмём модельную функцию — она модельная сознательно, зато считается на
бумаге:
f(x,y)=21(x2+κy2),∇f=(x,κy).
Градиентный спуск с шагом η распадается на две независимые геометрические
прогрессии:
xt+1=(1−η)xt,yt+1=(1−ηκ)yt.
Устойчивость требует ∣1−ηκ∣<1, то есть η<2/κ: крутая
координата запрещает большой шаг. А скорость по пологой координате равна
1−η — при η<2/κ она не может быть быстрее, чем
1−2/κ. Число κ (отношение кривизн, оно же число обусловленности)
целиком определяет беду: чем оно больше, тем сильнее разрыв между тем шагом,
который можно сделать, и тем, который нужен.
При наилучшем η=2/(1+κ) расстояние до минимума за один шаг умножается
на
ρ=κ+1κ−1,
и при κ=100 это ρ≈0,980 — на каждый шаг приходится всего два
процента прогресса. Чтобы сократить расстояние в 103 раз, нужно
T=ln(1/ρ)ln103≈0,02006,91≈346
шагов при κ=100 и примерно в десять раз больше при κ=1000: число
шагов растёт линейно по κ. Это не про «медленный компьютер», это про
форму чаши.
Почему шаг нельзя просто увеличить
Мы уже знаем, что шаг ограничен: крутая координата требует η<2/κ, иначе
прогрессия расходится. Теперь спросим, чего мы из-за этого лишаемся.
Представим, что шаги сделаны совсем мелкими, а считаем мы их очень часто. Точки
сольются в гладкую кривую, которая просто скатывается ко дну, всё время поворачивая в
сторону наискорейшего спуска. Назовём её идеальной траекторией и будем держать как
эталон: реальный метод идёт по ней рывками и ровно настолько хорош, насколько точно за
ней успевает.
Сравнение эталона с рывками сразу показывает, где потери. У идеальной кривой нет
ограничения на длину шага — она просто скользит по склону. У метода оно есть, и
диктует его самое крутое направление, каким бы редким оно ни было. Вдоль пологого дна
оврага разрешённый шаг оказывается чудовищно мал.
Рис. 62.2. Идеальная кривая идёт ко дну, а шаги за ней не поспевают
Овраг с обусловленностью κ=80. Синяя линия — идеальная траектория: она идёт ко
дну по дуге, не оглядываясь на длину шага. Красные точки — спуск с наилучшим шагом
0,025: они послушно ложатся на неё, потому что шаг мал. Зелёная
ломаная — тяжёлый шарик: он размашисто пересекает овраг, но приходит к минимуму за
44 шага против 277 у спуска.
Отсюда неожиданный вывод: ускорять надо не движение, а шаги. Идеальную кривую
подгонять бессмысленно — она и так скатывается со скоростью, какую позволяет форма
чаши. А вот метод делает сотни осторожных шажков там, где кривая проходит одним махом.
Значит, задача не «идти быстрее», а «складывать много мелких шагов в один
длинный вдоль дна, не расшатав движение поперёк».
Ровно это и делает инерция. Обычный шарик, скатываясь в чашу, не останавливается на
каждом миллиметре, чтобы заново посмотреть на уклон: у него есть скорость, и он
переносит её из прошлого в будущее. Метод с моментом устроен так же — слагаемое
β(xk−xk−1) и есть накопленная скорость, а множитель β<1 играет роль
трения, которое не даёт разогнаться до бесконечности. Поперёк оврага скорость на
соседних шагах меняет знак и гасит сама себя, а вдоль дна она копится шаг за шагом.
«Момент» здесь не красивое слово: это обычная механическая инерция, записанная в двух
строчках.
Momentum: память о направлении
Инерция накапливает скорость:
vt=βvt−1+gt,θt+1=θt−ηvt.
Ту же схему можно записать без вспомогательной переменной — как «шаг плюс доля
предыдущего смещения»:
θt+1=θt−ηgt+β(θt−θt−1),
откуда и старое название «метод тяжёлого шарика»: шарик с массой не может
мгновенно развернуться поперёк оврага.
Поперечные градиенты в овраге меняют знак почти каждый шаг и при суммировании
взаимно гасятся; продольные сохраняют знак и накапливаются. Это ровно то, что
нужно: подавить то, что мешает, усилить то, что ведёт к цели.
Модельный овраг f=x2+100y2, старт из точки (9;1), бюджет 60 вычисленных
градиентов, у каждого метода свой лучший η из сетки. GD доходит до
f=8,38, Momentum — до 0,020, Adam — до 0,0074. По дороге GD меняет
знак координаты y все 60 раз, Momentum — 13. Тот же бюджет, разница в тысячу
раз.
Числа с рисунка стоит проговорить вслух. Стартовое значение
f(9;1)=81+100=181. Градиентный спуск с наилучшим шагом снял с него меньше
чем в двадцать два раза; момент — почти в девять тысяч раз; Adam — в двадцать
четыре тысячи. Все трое считали одинаковое число градиентов, то есть потратили
одинаковые деньги.
Сколько шагов помнит инерция
Раскроем рекурсию:
vt=k=0∑t−1βkgt−k.
Это взвешенная сумма прошлого с геометрически убывающими весами. Сумма весов
при постоянном градиенте равна
k≥0∑βk=1−β1,
то есть эффективный шаг вдоль устойчивого направления вырастает в
1/(1−β) раз: при β=0,9 — в десять, при β=0,99 — в сто.
Характерная глубина памяти тоже равна 1/(1−β) шагов.
Нестеровская версия вычисляет градиент не в текущей точке, а в сдвинутой по уже
накопленной скорости:
vt=βvt−1+∇f(θt−ηβvt−1),θt+1=θt−ηvt.
Смысл поправки — «сначала посмотри, куда тебя несёт, потом измеряй наклон». Для
гладких выпуклых задач это даёт доказуемо лучшую оценку числа шагов; в
нейросетях выигрыш зависит от режима, и его надо измерять, а не предполагать.
AdaGrad: редкая координата получает шанс
Инерция работает с направлением. Второе семейство работает с масштабом
координаты. AdaGrad копит квадраты градиентов покоординатно:
Gt,j=s≤t∑gs,j2,θt+1,j=θt,j−Gt,j+εηgt,j.
Это в точности шаг в изменённой метрике: если ввести диагональную матрицу
Ht=diag(Gt,1,…,Gt,d),
то обновление записывается как θt+1=θt−ηHt−1gt —
формально то же самое, что растяжение осей перед обычным спуском.
Координата, по которой градиент часто велик, быстро набирает G и получает
маленький множитель; редкая координата сохраняет крупный шаг. Это ровно тот
случай, что описан в уроке 24 для разреженных текстов: вес слова,
встретившегося в пяти письмах из четырёх с половиной тысяч, не должен тащить на
себе тормоз, заработанный словом «to».
Проверим это на настоящем корпусе SMS-спама, с которым мы работали в
уроке 42: 4457 обучающих сообщений, словарь из 1553 слов,
встретившихся не менее чем в пяти письмах, заполненность матрицы признаков
0,78 % — то есть 99,2 % всех клеток нули.
Рис. 62.2. Реальный разреженный текст: редкому слову — крупный шаг
Слева: множитель 1/G после трёх эпох на реальном SMS-спаме. Медиана у
слов из 5–8 писем — 153,0; у слов, встретившихся хотя бы в 300 письмах, — 6,1.
Разрыв в 25 раз возник сам собой, из истории градиентов. Справа: точность на
1115 отложенных сообщениях при собственном лучшем η для каждого метода —
SGD 98,30 %, AdaGrad 98,74 %, Adam 98,83 %.
У вечной суммы есть цена: Gt,j только растёт, поэтому шаг монотонно
затухает. На выпуклой задаче это даже доказуемо полезно, но при долгом обучении
нейросети метод может остановиться раньше, чем найдёт хорошее решение.
RMSProp и экспоненциальная память
RMSProp заменяет вечную сумму скользящим средним:
vt=β2vt−1+(1−β2)gt2,θt+1=θt−ηvt+εgt.
Развернув рекурсию, видим взвешенное среднее прошлых квадратов с суммой весов,
равной единице (с точностью до начального смещения):
vt=(1−β2)k=0∑t−1β2kgt−k2.
Квадраты берутся покоординатно, старое забывается геометрически, окно памяти —
порядка 1/(1−β2) шагов: при β2=0,9 это десяток, при
β2=0,999 — тысяча.
Модельный опыт: градиент равен 0,1, а на шаге 20 случайно оказался равен
3. Множитель шага AdaGrad падает с 2,24 и к сотому шагу стоит на
0,31 — в 7,1 раза ниже, чем был; событие давней истории всё ещё тормозит
обучение. RMSProp с β2=0,9 возвращает половину прежнего шага через
34 шага и приходит в пределы 10 % через 67.
Adam соединяет два момента
Adam хранит экспоненциальные средние и градиента, и его квадрата:
Полезное следствие: длина шага почти не зависит от величины градиента. Если
градиент по координате стабилен, то m≈g и
v≈∣g∣, поэтому
∣Δθj∣≈η∣gj∣∣gj∣=η.
Adam переводит η из «множителя при градиенте» в «размер шага в единицах
весов» — отсюда и знаменитое значение по умолчанию 10−3, которое работает
в задачах с совершенно разными масштабами потерь.
Слова «инвариантен к диагональному перемасштабированию» — самые важные в этой
цитате. Умножьте одну координату признака на тысячу: градиент по
соответствующему весу тоже умножится на тысячу, но и v умножится на
тысячу, и отношение не изменится. Именно эту инвариантность мы сейчас увидим на
настоящих данных.
Зачем нужна коррекция смещения
Инициализация m0=v0=0 — не безобидная деталь. При постоянном g=1 имеем
m1=1−β1=0,1 и v1=1−β2=0,001, поэтому без коррекции первый
множитель равен
v1m1=0,03160,1=10≈3,16,
то есть первый шаг был бы втрое длиннее задуманного η. Коррекция делит на
1−β1t и 1−β2t и возвращает обеим оценкам правильный масштаб.
Постоянный градиент g=1. Некорректированный mt доползает до 0,99
только к шагу 44 — почти полсотни шагов метод недооценивает направление.
Исправленные mt и vt равны единице точно, при любом
t. Справа виден побочный эффект несимметричной инициализации: без коррекции
самый первый шаг был бы в 10≈3,16 раза длиннее.
Реальные данные: когда масштабы врозь
Модельный овраг убедителен, но настоящие овраги не рисуют — их получают.
Возьмём данные диагностики опухолей молочной железы из sklearn (569 объектов,
30 признаков) и обучим логистическую регрессию полным градиентом, 300 итераций.
Признаки берём сырыми, как они записаны в файле: наибольшее стандартное
отклонение превосходит наименьшее в 215 тысяч раз.
Рис. 62.5. Сырые признаки против стандартизованных
Слева — сырые признаки: за 300 итераций GD доходит до потери 0,250,
Momentum до 0,199, RMSProp до 0,229, AdaGrad до 0,176, Adam до
0,098. Справа — те же данные после стандартизации: 0,040; 0,037;
0,035; 0,038; 0,027. Разрыв между лучшим и худшим сжался с 2,5 раза
до 1,5. У каждого метода свой лучший η из сетки в 33 значения от
10−7 до 10; начальная потеря у всех одна и та же, ln2=0,693.
Вывод из этой пары панелей стоит десятка формул: адаптивные методы в основном
делают ту работу, которую вы не сделали при подготовке данных. Стандартизация
дешевле, проверяемее и не мешает никакому оптимизатору.
Один и тот же шаг — нечестное сравнение
Самая частая ошибка в отчётах: «мы сравнили оптимизаторы при η=10−3».
Масштаб обновления у методов разный по построению. У GD сдвиг пропорционален
∣g∣; у Adam он близок к η независимо от ∣g∣, потому что
m/v по модулю порядка единицы. Никакого общего
η не существует.
Рис. 62.6. У каждого метода своя рабочая зона шага
Те же реальные данные, 200 итераций, полная сетка η. Лучший шаг у GD —
3,2⋅10−5 (потеря 0,288), у Adam — 3,2⋅10−2 (потеря
0,134): разница в тысячу раз. Если всем выдать «удобный» шаг Adam, GD
покажет потерю 188, а Momentum — 101, то есть оба развалятся, и вывод
«адаптивные методы лучше» будет получен из ничего.
Лаборатория оптимизаторов
GD, Momentum, AdaGrad и Adam в одном овраге
График шире экрана — листайте по горизонтали →
Загружается живая иллюстрация…
По умолчанию лаборатория работает честно: каждому методу она подбирает свой
лучший η из сетки, ровно как рисунок 62.6. Начните с κ=1: круглая
чаша, все четверо приходят в минимум почти сразу — на симметричной задаче
адаптивность не нужна. Поднимайте κ и следите за счётчиком пересечений
оси: у GD он растёт первым, и найденный для него η упирается в потолок
2/κ.
Затем переключите режим на «общий η для всех» и поднимайте шаг: вы увидите
три разных порога устойчивости и то самое несправедливое сравнение, о котором
шла речь выше. И наконец включите шум градиента σ: на гладкой
детерминированной чаше покоординатная нормировка почти творит чудеса, но как
только v начинает измерять не сигнал, а шум, порядок методов меняется.
Именно поэтому выводы, полученные на модельной квадратичной задаче, нельзя
переносить на обучение сети без проверки.
AdamW: decay, который снова стал сжатием
Для обычного SGD штраф 2λ∥θ∥2 и «затухание весов» —
одно и то же:
θ←θ−η(g+λθ)=(1−ηλ)θ−ηg.
В Adam это равенство ломается: слагаемое λθ попадает в градиент,
проходит через покоординатное деление на v и сжимает разные
веса по-разному. Координата с малым v получает огромное сжатие,
координата с большим — почти никакого. AdamW отделяет decay от градиента:
Реальные данные, стандартизованные признаки, λ=0,05, η=0,05,
400 шагов. Норма весов: без decay 5,84, с L2 внутри градиента 1,42,
у AdamW 4,60. Но главное — справа: коэффициент сжатия отдельных координат у
L2-варианта разбросан в 81,9 раза, у AdamW — лишь в 5,1. Один и тот же
λ означает у них совершенно разную регуляризацию.
Практический вывод для регуляризации: число λ без имени
оптимизатора ничего не значит, а переход с Adam на AdamW требует заново
настроить λ, а не переписать одну букву в конфигурации.
Шор: растяжение пространства вместо угадывания шага
Мысль «поменяем метрику вместо того, чтобы мучить шаг» появилась задолго до
AdaGrad, и появилась она в Киеве. Наум Зуселевич Шор (1937–2006), сотрудник
Института кибернетики имени В. М. Глушкова, занимался задачами, где функция
негладкая и обычный градиент попросту не определён. На рубеже 1960–1970-х годов
он предложил
субградиентные методы с растяжением пространства: после каждого шага
координаты пересчитываются линейным преобразованием, вытягивающим то
направление, вдоль которого метод топчется. Знаменитый r-алгоритм Шора
растягивает пространство в направлении разности двух последовательных
субградиентов — то есть ровно в том направлении, где ландшафт оказался оврагом.
θt+1=θt−ηtBtBt⊤gt,
где матрица Bt обновляется после каждого шага так, чтобы растянуть
пространство вдоль gt−gt−1. Сравните с AdaGrad: там роль BtBt⊤
играет диагональная матрица diag(Gt,j−1/2). Идея одна и
та же — заменить метрику; отличается только цена.
Обрезка градиента и численная точность
Иногда норма градиента взрывается — обычно в рекуррентных сетях или при
неудачном сочетании шага и батча. Клиппинг по норме заменяет
g←g⋅min(1,∥g∥c),
сохраняя направление и ограничивая длину числом c. Иначе говоря, на обрезанных
шагах метод работает с уменьшенной скоростью обучения
ηэфф=η∥g∥c,
и чем сильнее выброс, тем сильнее автоматическое торможение. Покоординатная
обрезка устроена иначе: она поворачивает вектор, и это надо оговаривать в
отчёте.
Численная точность тоже участвует в траектории. В смешанной точности малые
градиенты округляются в ноль; loss scaling временно увеличивает их до
представимого диапазона и делит обратно перед шагом:
L~=S⋅L,g=S1∇L~,S∼104.
Появление NaN не доказывает, что плохо выбрана функция потерь, пока не проверены переполнение,
ε и порядок операций.
Быстрый train не гарантирует лучший test
Adam почти всегда быстрее уменьшает обучающую потерю — мы это и увидели. Но
обучение не соревнование по скорости спуска. В переопределённом режиме из
урока 59 существует целое многообразие параметров, дающих почти
нулевую ошибку на обучении; оптимизатор молча выбирает из него один, и этот
выбор — часть модели, а не часть вычислительной техники.
Спорить с этой цитатой можно и нужно: в трансформерах картина другая, там
AdamW стал стандартом не от лени. Но методологический смысл её бесспорен:
«достиг той же train loss» и «построил ту же функцию» — разные утверждения, и
второе проверяется только на отложенных данных.
Как выбирать оптимизатор: короткий протокол
Порядок действий, который экономит месяцы:
Приведите признаки к сопоставимым масштабам и проверьте нормализацию внутри
сети. Половина «плохой обусловленности» лечится здесь и бесплатно.
Возьмите проверенный baseline: AdamW для трансформеров, SGD с моментом для
многих задач зрения, AdaGrad для разреженных выпуклых моделей.
Настройте η по логарифмической сетке и выберите расписание. Это дороже
и важнее, чем выбор между Adam и SGD.
Только потом трогайте λ, β1, β2 и размер батча. По
одному решению за раз.
Логируйте норму градиента, долю обрезанных шагов и отношение
∥Δθ∥/∥θ∥ по слоям. Диагностика дешевле перебора.
Сравнивайте на нескольких seeds и по validation, а тест открывайте один раз
в конце, как договаривались в уроке 58.
Обратное распространение из урока 25 даёт нам gt; оптимизатор
решает, что с ним делать. Ни один из них не знает истинной матрицы кривизны и
не обязан её знать: каждый строит дешёвую догадку о геометрии по той истории,
что уже видел. Понимать, какую именно догадку строит ваш метод, — и значит
уметь выбирать оптимизатор.