← Назад к вопросам

Какие знаешь оптимизаторы, в чем их идеи и различия?

1.8 Middle🔥 172 комментариев
#Глубокое обучение#Машинное обучение

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Оптимизаторы в глубоком обучении: полный обзор

Оптимизаторы — это алгоритмы обновления весов сети при обучении. Это фундамент successful training. Рассмотрю все популярные подробно.

Основная идея оптимизаторов

Задача: Минимизировать loss функцию L(w)

Итеративный процесс:
1. Вычисляем градиент: ∇L(w)
2. Обновляем веса: w_new = w_old - α * градиент
3. Повторяем

Разные оптимизаторы отличаются в шаге 2:
- Как быстро обновляем (learning rate)
- Используем ли историю градиентов
- Адаптируем ли rate к разным параметрам

1. SGD (Stochastic Gradient Descent) — базовый

Самый простой и понятный оптимизатор.

# Математика:
w_t = w_{t-1} - α * ∇L(w_{t-1})

Где:
α — learning rate (скорость обучения)
∇L(w) — градиент функции потерь

Реализация:

import torch
from torch.optim import SGD

model = MyModel()
optimizer = SGD(model.parameters(), lr=0.01)  # lr = learning rate

for epoch in range(100):
    for X_batch, y_batch in train_loader:
        # Forward pass
        outputs = model(X_batch)
        loss = criterion(outputs, y_batch)
        
        # Backward pass
        optimizer.zero_grad()  # Обнуляем старые градиенты
        loss.backward()        # Вычисляем градиенты
        optimizer.step()       # Обновляем веса

Плюсы:

  • Простой и понятный
  • Низкое потребление памяти
  • Работает (если подобрать learning rate)

Минусы:

  • Медленная сходимость
  • Одинаковый learning rate для всех параметров
  • Застревает в локальных минимумах
  • Нужно подбирать learning rate вручную

2. Momentum — с инерцией

Добавляет инерцию (как мяч катится с горы).

# Математика:
v_t = β * v_{t-1} + ∇L(w_t)     (накапливаем градиент)
w_t = w_{t-1} - α * v_t          (используем накопленный импульс)

Обычно β = 0.9

Идея: Если градиент показывает в одном направлении несколько раз подряд, увеличиваем шаг в этом направлении.

optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)

# То же самое что и выше, но с momentum!
for epoch in range(100):
    for X_batch, y_batch in train_loader:
        outputs = model(X_batch)
        loss = criterion(outputs, y_batch)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()  # Теперь с инерцией

Плюсы:

  • Быстрее SGD
  • Преодолевает локальные минимумы
  • Ускоряет сходимость

Минусы:

  • Может "перепрыгнуть" минимум
  • Другой гиперпараметр (momentum = β)

3. Nesterov Momentum — улучшенный momentum

Заглядывает на один шаг вперёд перед вычислением градиента.

# Математика:
v_t = β * v_{t-1} + ∇L(w_{t-1} - α * v_{t-1})  # Заглядываем вперёд!
w_t = w_{t-1} - α * v_t
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9, nesterov=True)

Плюсы:

  • Немного быстрее чем обычный momentum
  • Умнее выбирает направление

Минусы:

  • Сложнее понять
  • Маргинальное улучшение

4. AdaGrad — адаптивный learning rate

Разные параметры обновляются с разной скоростью.

# Математика:
g_t = ∇L(w_t)                              # Текущий градиент
G_t = G_{t-1} + g_t²                       # Накапливаем квадраты
w_t = w_{t-1} - (α / √(G_t + ε)) * g_t    # Адаптивный learning rate

Где:
G_t — накопленная сумма квадратов градиентов
ε — маленькое число для стабильности (1e-8)

Идея: Параметры с большими градиентами → уменьшаем их learning rate. Параметры с малыми градиентами → увеличиваем их learning rate.

optimizer = torch.optim.Adagrad(model.parameters(), lr=0.01)

Плюсы:

  • Адаптивный learning rate
  • Не требует подбора momentum
  • Хорошо для sparse данных

Минусы:

  • Learning rate монотонно падает → может зафиксироваться
  • G_t растёт без ограничения
  • В конце обучения learning rate может быть очень маленьким

5. RMSprop — улучшенный AdaGrad

Исправляет проблему зануляющегося learning rate в AdaGrad.

# Математика:
v_t = β * v_{t-1} + (1 - β) * (∇L(w_t))²  # Экспоненциальное сглаживание
w_t = w_{t-1} - (α / √(v_t + ε)) * ∇L(w_t)

Обычно β = 0.9

Идея: Вместо накопления всех старых градиентов, берём их экспоненциально взвешенное среднее.

optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001, alpha=0.99)

Плюсы:

  • Фиксит проблему AdaGrad
  • Адаптивный learning rate
  • Хороший баланс

Минусы:

  • Ещё один гиперпараметр (beta/alpha)

6. ADAM (Adaptive Moment Estimation) — КОРОЛЬ оптимизаторов

Комбинирует лучшее из Momentum и RMSprop.

# Математика:
m_t = β₁ * m_{t-1} + (1 - β₁) * ∇L(w_t)          # 1st moment (mean)
v_t = β₂ * v_{t-1} + (1 - β₂) * (∇L(w_t))²       # 2nd moment (variance)

m̂_t = m_t / (1 - β₁ᵗ)                             # Bias correction
v̂_t = v_t / (1 - β₂ᵗ)

w_t = w_{t-1} - α * m̂_t / (√v̂_t + ε)

Обычно β₁ = 0.9, β₂ = 0.999, ε = 1e-8

Идея:

  • m_t = "импульс" (как momentum)
  • v_t = "адаптивный rate" (как RMSprop)
  • Combine both!
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)  # lr обычно 0.001

# Это самый популярный оптимизатор!
for epoch in range(100):
    for X_batch, y_batch in train_loader:
        outputs = model(X_batch)
        loss = criterion(outputs, y_batch)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()  # ADAM делает "умное" обновление

Плюсы:

  • Работает отлично на большинстве задач
  • Мало гиперпараметров
  • Быстрая сходимость
  • Default learning rate часто подходит (0.001)
  • Мало требует подбора

Минусы:

  • Может сходиться к более плохому решению (на некоторых задачах)
  • Требует больше памяти (хранит m и v)
  • Может переобучиться если не добавить regularization

Сравнение оптимизаторов

┌─────────────┬──────────┬──────────┬────────┬──────────┬──────────┐
│ Оптимизатор │ Скорость │ Качество │ Память │ Гиперп. │ Популяр. │
├─────────────┼──────────┼──────────┼────────┼──────────┼──────────┤
│ SGD         │ ✓        │ ★★★     │ ✓✓✓   │ ✓✓       │ ★★       │
│ Momentum    │ ★★       │ ★★★     │ ✓✓    │ ★★       │ ★★★      │
│ Nesterov    │ ★★★      │ ★★★     │ ✓✓    │ ★★       │ ★★       │
│ AdaGrad     │ ★★       │ ★★      │ ✓     │ ★★★      │ ★        │
│ RMSprop     │ ★★★      │ ★★★     │ ✓✓    │ ★★★      │ ★★       │
│ ADAM        │ ★★★      │ ★★★★    │ ✓     │ ★★★★     │ ★★★★★    │
└─────────────┴──────────┴──────────┴────────┴──────────┴──────────┘

Другие современные оптимизаторы

AdamW (ADAM + Weight Decay)

# Правильная L2 регуляризация!
optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)

# Vs просто Adam с L2:
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=0.01)  # Неправильно!

# AdamW лучше для регуляризации на больших моделях

LAMB (Layer-wise Adaptive Moments)

optimizer = torch.optim.LAMB(model.parameters(), lr=0.001)

# Хорош для очень больших batch sizes (DDP training)

RAdam (Rectified Adam)

from torch.optim import RAdam

optimizer = RAdam(model.parameters(), lr=0.001)

# Лучше на маленьких batch sizes
# Исправляет большую дисперсию в начале обучения

Learning Rate Schedulers (изменение скорости обучения)

import torch.optim.lr_scheduler as lr_scheduler

optimizer = torch.optim.Adam(model.parameters())

# 1. Step decay (каждые N эпох умножаем на 0.1)
scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)

# 2. Exponential decay
scheduler = lr_scheduler.ExponentialLR(optimizer, gamma=0.95)

# 3. Cosine annealing (график как косинус)
scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=100)

# 4. Warmup + decay (популярно в Transformers)
from torch.optim.lr_scheduler import LambdaLR
def warmup_lambda(epoch):
    if epoch < 10:
        return epoch / 10
    else:
        return 1.0 - (epoch - 10) / 90
scheduler = LambdaLR(optimizer, lr_lambda=warmup_lambda)

# Использование:
for epoch in range(100):
    train_one_epoch()
    scheduler.step()  # Обновляем learning rate

Практические советы

# 1. ДЛЯ БОЛЬШИНСТВА ЗАДАЧ:
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# Просто работает!

# 2. ДЛЯ БОЛЬШИХ МОДЕЛЕЙ (BERT, GPT):
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5, weight_decay=0.01)
scheduler = lr_scheduler.LinearLR(optimizer, start_factor=0.1, total_iters=1000)

# 3. ДЛЯ CNN + Computer Vision:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9, nesterov=True)
scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

# 4. ДЛЯ ОЧЕНЬ БОЛЬШИХ BATCH SIZES (Multi-GPU):
optimizer = torch.optim.LAMB(model.parameters(), lr=0.1)

# 5. ДЛЯ МАЛЕНЬКИХ ДАТАСЕТОВ:
optimizer = torch.optim.RAdam(model.parameters(), lr=0.001)

# 6. С L2 РЕГУЛЯРИЗАЦИЕЙ:
optimizer = torch.optim.AdamW(model.parameters(), weight_decay=0.01)

Визуализация оптимизаторов

import numpy as np
import matplotlib.pyplot as plt

# Траектории разных оптимизаторов на контурной карте
fig, axes = plt.subplots(2, 3, figsize=(15, 10))

# Каждый subplot показывает как разный оптимизатор идёт к минимуму
for ax, (name, optimizer_class) in enumerate([
    ('SGD', torch.optim.SGD),
    ('Momentum', lambda p: torch.optim.SGD(p, momentum=0.9)),
    ('Adam', torch.optim.Adam),
    ('AdaGrad', torch.optim.Adagrad),
    ('RMSprop', torch.optim.RMSprop)
]):
    # Симуляция оптимизации на 2D функции
    # ...
    # Рисуем trajectory

Как выбрать оптимизатор

Процесс выбора:

1. НАЧНИ с Adam
   → Работает 80% времени
   → Мало нужно подбирать

2. Если не работает хорошо:
   → Попробуй SGD + Momentum
   → Попробуй AdamW + scheduler
   → Попробуй RMSprop

3. Если очень большая модель:
   → AdamW или LAMB
   → С learning rate scheduler

4. Если маленькое количество данных:
   → RAdam (менее нестабильен в начале)

5. Если Computer Vision большие модели:
   → SGD + Momentum + scheduler
   → (исторически хорошо работает)

6. Если NLP Transformer:
   → AdamW + Linear scheduler + warmup
   → (стандарт в Hugging Face)

Заключение

Важные оптимизаторы:

  1. SGD — baseline, понимать как работает
  2. Momentum — добавляет инерцию
  3. Adam — король, используй по умолчанию
  4. AdamW — лучше Adam с регуляризацией
  5. RMSprop — хороший выбор для RNN

Главное правило:

┌─────────────────────────┐
│ Начни с Adam            │
│ Добавь scheduler        │
│ Если плохо → SGD + Mom  │
│ Если ок → добавь L2     │
│ Готово!                 │
└─────────────────────────┘

Learning rate:

  • Adam: 0.0001 - 0.01 (обычно 0.001)
  • SGD: 0.01 - 0.1
  • Трансформеры: 1e-5 - 5e-5

Главное: не бойся экспериментировать! Основы везде одинаковые.