В чем разница между SGD (стохастическим градиентным спуском) и обычным (пакетным) градиентным спуском?

«В чем разница между SGD (стохастическим градиентным спуском) и обычным (пакетным) градиентным спуском?» — вопрос из категории Нейронные сети и Deep Learning, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Разница заключается в объеме данных, используемых для вычисления градиента и обновления весов модели на одной итерации (шаге).

Метод Объем данных на шаг Скорость / Вычисления Сходимость / Шум
Batch Gradient Descent (Пакетный GD) Весь тренировочный набор данных. Медленно. Требует больших вычислительных ресурсов и памяти, так как нужно обработать все данные перед одним обновлением. Плавная, детерминированная сходимость по направлению к локальному минимуму. Может застрять в нем.
Stochastic Gradient Descent (Стохастический GD) Один случайный тренировочный пример. Очень быстро. Обновление весов происходит после каждого примера, что позволяет быстро делать много шагов. Очень шумная, нестабильная траектория. Шум может помочь "выпрыгнуть" из плохих локальных минимумов, но усложняет точную сходимость.
Mini-batch Gradient Descent Небольшая случайная подвыборка (mini-batch), например, 32 или 128 примеров. Компромисс. Достаточно быстрый и эффективный по памяти. Является стандартом на практике. Умеренный шум, баланс между скоростью и стабильностью сходимости.

Почему Mini-batch SGD стал стандартом?

  1. Эффективность GPU: Позволяет полностью загрузить вычислительные ядра графического процессора параллельной обработкой батча.
  2. Стабильность: Градиент, усредненный по нескольким примерам, менее шумный, чем от одного примера, что ведет к более устойчивой сходимости.
  3. Скорость: Одно обновление на батч быстрее, чем проход по всему датасету (Batch GD).

Иллюстрация на псевдокоде:

# Псевдокод для сравнения логики обновления весов (w)

# Batch Gradient Descent
for epoch in range(num_epochs):
    gradient = compute_gradient(w, entire_training_set)  # ДОРОГО!
    w = w - learning_rate * gradient  # Одно обновление за эпоху

# Stochastic Gradient Descent (SGD)
for epoch in range(num_epochs):
    for x_i, y_i in training_set:  # Итерация по КАЖДОМУ примеру
        gradient = compute_gradient(w, x_i, y_i)  # Дешево, но шумно
        w = w - learning_rate * gradient  # Много обновлений за эпоху

# Mini-batch Gradient Descent (ПРАКТИЧЕСКИЙ СТАНДАРТ)
for epoch in range(num_epochs):
    for batch in dataloader:  # Итерация по БАТЧАМ (например, по 32 примера)
        x_batch, y_batch = batch
        gradient = compute_gradient(w, x_batch, y_batch)  # Оптимально
        w = w - learning_rate * gradient

В современных фреймворках (PyTorch, TensorFlow) оптимизатор SGD по умолчанию реализует именно Mini-batch SGD. Пакетный градиентный спуск на больших данных практически не используется из-за непрактичных требований к памяти.