Градиентный спуск

Материал из llmdocs — справочник разработчика
Портал: ML и MLOps
Градиентный спуск
Типметод оптимизации первого порядка
ПредложенОгюстен Коши (1847)
Стохастический вариантРоббинс и Монро (1951)
Ключевой гиперпараметртемп обучения (learning rate)
Популярные оптимизаторыSGD с моментом, Adam, AdamW
Вычисление градиента в нейросетяхобратное распространение ошибки

Градиентный спуск (англ. gradient descent) — итеративный метод поиска минимума функции: на каждом шаге параметры сдвигаются в направлении, противоположном градиенту, то есть туда, где функция убывает быстрее всего. В машинном обучении минимизируется функция потерь — мера ошибки модели на данных, — а параметрами служат веса модели. Почти все нейросети, включая большие языковые модели, обучаются одним из вариантов градиентного спуска.[3]

Идея

Градиент $\nabla L(\theta)$ — вектор частных производных функции потерь по каждому параметру; он указывает направление наискорейшего роста. Шаг обновления:

$$\theta \leftarrow \theta - \eta \, \nabla L(\theta)$$

где $\eta$ — темп обучения (learning rate). Образ — спуск с горы в тумане: видно только наклон под ногами, и путник каждый раз шагает вниз по склону.

Метод описал Огюстен Коши в 1847 году. Для нейросетей он стал практичным после популяризации обратного распространения ошибки (backpropagation, 1986) — алгоритма, вычисляющего градиент по всем весам за один проход назад по сети с помощью цепного правила.[6] Сейчас это делают автоматически фреймворки вроде PyTorch.

Темп обучения

Самый важный гиперпараметр. Слишком маленький темп — обучение идёт мучительно долго и застревает; слишком большой — шаги «перепрыгивают» минимум, потери скачут или уходят в бесконечность. На практике темп меняют по расписанию: короткий разогрев (warmup) с нуля, затем плавное снижение — косинусное или ступенчатое.

Варианты по объёму данных

Вариант Градиент считается по Свойства
Полный (batch) всей выборке точный, но дорогой шаг; не помещается в память
Стохастический (SGD) одному примеру шумный, дешёвый шаг
Мини-батч группе из 32–4096 примеров компромисс, стандарт на практике

Стохастический подход восходит к работе Роббинса и Монро 1951 года.[5] Шум мини-батчей не только экономит вычисления, но и помогает выбираться из неудачных областей и, по-видимому, способствует лучшему обобщению. Под «SGD» сегодня почти всегда понимают мини-батчевый вариант.

Оптимизаторы

Поверх базового шага придуманы улучшения:[1]

  • Момент (momentum) — накапливает «скорость» из предыдущих градиентов, сглаживая колебания в узких оврагах функции потерь. Вариант — момент Нестерова.
  • Адаптивные методы — AdaGrad, RMSProp — подбирают свой темп для каждого параметра по истории его градиентов.
  • Adam (2014) сочетает момент и адаптивный темп и стал выбором по умолчанию для нейросетей.[2] AdamW правильно отделяет регуляризацию весов от шага (см. Переобучение и регуляризация) и используется при обучении трансформеров.
import torch

model = torch.nn.Linear(10, 1)
opt = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=0.01)
loss_fn = torch.nn.MSELoss()

for xb, yb in loader:            # мини-батчи
    opt.zero_grad()
    loss = loss_fn(model(xb), yb)
    loss.backward()              # обратное распространение: градиенты
    opt.step()                   # шаг градиентного спуска

Трудности

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

Где ещё применяется

Градиентный бустинг — тоже градиентный спуск, только в пространстве функций: каждое новое дерево аппроксимирует антиградиент потерь. Линейные модели в scikit-learn (SGDClassifier) обучаются SGD на данных, не помещающихся в память.

См. также

Источники

  1. Ruder — An overview of gradient descent optimization algorithms (2016)
  2. Kingma, Ba — Adam: A Method for Stochastic Optimization (2014)
  3. Goodfellow, Bengio, Courville — Deep Learning, гл. 8
  4. PyTorch — torch.optim
  5. Robbins, Monro — A Stochastic Approximation Method (1951)
  6. Rumelhart, Hinton, Williams — Learning representations by back-propagating errors (1986)