Adam Optimizer
Adam сочетает моментум с размером шага для каждого параметра, масштабированным по недавним значениям градиента. Правило обновления, значения по умолчанию, AdamW и сравнение Adam с SGD.
Оптимизатор Adam, сокращение от Adaptive Moment Estimation, — это алгоритм оптимизации для обучения нейронных сетей, который подбирает собственный адаптивный размер шага для каждого параметра. Представленный Кингмой и Ба в статье Adam: метод стохастической оптимизации, он расширяет стохастический градиентный спуск (SGD), используя скользящие средние прошлых градиентов и их квадратов. Быстрый прогресс на ранних этапах и устойчивость к настройкам по умолчанию сделали Adam наиболее распространённым оптимизатором для начала работы в глубоком обучении, а его вариант AdamW стал стандартным выбором для обучения трансформеров и больших языковых моделей.
Как работает Adam#
Обучение минимизирует функцию потерь, многократно корректируя каждый вес в направлении, заданном его градиентом. Обычный SGD умножает каждый градиент на один и тот же темп обучения. Adam хранит два дополнительных значения для каждого параметра и обновляет их на каждом шаге t, используя текущий градиент g:
- Первый момент (импульс):
m = β1·m + (1 − β1)·g— экспоненциально затухающее среднее градиентов, которое помогает обновлению двигаться в одном направлении. - Второй момент:
v = β2·v + (1 − β2)·g²— затухающее среднее квадратов градиентов, показывающее типичный размер градиентов каждого параметра. - Коррекция смещения:
m̂ = m / (1 − β1^t)иv̂ = v / (1 − β2^t)компенсируют то, что оба средних значения изначально равны нулю. - Обновление:
θ = θ − lr · m̂ / (√v̂ + ε).
В статье использованы значения по умолчанию, которые также применяет torch.optim.Adam в PyTorch: lr = 0.001, β1 = 0.9, β2 = 0.999 и ε = 1e-8. Деление на √v̂ нормализует каждый шаг по типичному размеру градиента параметра, поэтому шаги остаются близкими к темпу обучения независимо от того, малы градиенты или велики. В зашумлённых направлениях шаги уменьшаются, поскольку положительные и отрицательные градиенты взаимно компенсируются внутри m̂. Приведённый ниже фрагмент сравнивает первый шаг SGD и Adam для двух параметров, градиенты которых различаются по величине в 1 000 раз:
import torch
# Two parameters whose gradients differ in scale by 1,000x
scale = torch.tensor([1000.0, 1.0])
for name, optimizer_cls in [("SGD", torch.optim.SGD), ("Adam", torch.optim.Adam)]:
w = torch.zeros(2, requires_grad=True)
optimizer = optimizer_cls([w], lr=0.001)
loss = (scale * w).sum() # gradient is [1000, 1]
loss.backward()
optimizer.step()
print(f"{name} first step: {[round(v, 4) for v in w.tolist()]}")SGD перемещает первый параметр к -1.0, а второй — к -0.001: разница в 1 000 раз соответствует разнице градиентов. Adam перемещает оба ровно на величину темпа обучения — -0.001, поскольку нормализованный шаг зависит от направления и согласованности градиента, а не от его исходной величины.
Adam и AdamW#
В распространённых реализациях Adam применяет затухание весов — разновидность регуляризации в виде L2-штрафа, добавляемого к градиенту. Затем этот штраф, как и всё остальное, делится на √v̂, поэтому параметры с большими градиентами почти не регуляризуются. Развязанное затухание весов, предложенное Лошчиловым и Хаттером, устраняет эту проблему: веса напрямую уменьшаются на каждом шаге независимо от адаптивного обновления. В экспериментах авторов статьи AdamW лучше обобщал, чем Adam, на задачах классификации изображений; он доступен как torch.optim.AdamW.
Adam и SGD#
SGD с импульсом использует один общий темп обучения и хранит один буфер на параметр, а Adam хранит два — 8 байт на параметр при 32-битной точности. Для модели с 7 миллиардами параметров состояние оптимизатора занимает 56 ГБ. Adam обычно быстрее продвигается в начале обучения, меньше зависит от темпа обучения и гораздо надёжнее обучает трансформеры, чем SGD. Хорошо настроенный SGD часто достигает такой же или более высокой конечной точности на свёрточных моделях изображений, а Уилсон и соавторы обнаружили, что на проверенных ими задачах классификации изображений и обработки языка адаптивные методы часто обобщали хуже, чем SGD.
Обучение Ultralytics YOLO отражает этот компромисс: параметр optimizer="auto" по умолчанию выбирает AdamW с начальным темпом обучения, подобранным под число классов, для запусков длительностью до 10 000 итераций; для более длинных расписаний используется MuSGD — гибрид SGD и Muon. При явном выборе оптимизатора нужно также задать темп обучения, поскольку значение lr0=0.01 по умолчанию подходит для SGD и в десять раз выше обычного темпа обучения Adam.
from ultralytics import YOLO
# Загрузи предварительно обученную модель YOLO26n
model = YOLO("yolo26n.pt")
# Обучение с AdamW и начальным темпом обучения, подходящим для Adam
results = model.train(data="coco8.yaml", epochs=5, optimizer="AdamW", lr0=0.001)Когда YOLO26 обучается с оптимизатором семейства Adam, аргумент momentum (по умолчанию 0.937) задаёт β1, а значение β2 остаётся равным 0.999.
Adam и смежные оптимизаторы#
- AdaGrad: Делит каждый шаг на корень из суммы квадратов всех прошлых градиентов, поэтому размер шагов только уменьшается. Этот метод подходит для разреженных признаков, но замедляет длительные циклы обучения.
- RMSProp: Заменяет скользящую сумму AdaGrad экспоненциально затухающим средним квадратов градиентов. По сути, Adam — это RMSProp с импульсом и коррекцией смещения.
- Muon: Оптимизатор для двумерных матриц весов скрытых слоёв, который ортогонализует каждое обновление импульса с помощью итераций Ньютона — Шульца и хранит один буфер состояния на параметр — вдвое меньше, чем Adam.










