Ответ
Разница заключается в объеме данных, используемых для вычисления градиента и обновления весов модели на одной итерации (шаге).
| Метод | Объем данных на шаг | Скорость / Вычисления | Сходимость / Шум |
|---|---|---|---|
| Batch Gradient Descent (Пакетный GD) | Весь тренировочный набор данных. | Медленно. Требует больших вычислительных ресурсов и памяти, так как нужно обработать все данные перед одним обновлением. | Плавная, детерминированная сходимость по направлению к локальному минимуму. Может застрять в нем. |
| Stochastic Gradient Descent (Стохастический GD) | Один случайный тренировочный пример. | Очень быстро. Обновление весов происходит после каждого примера, что позволяет быстро делать много шагов. | Очень шумная, нестабильная траектория. Шум может помочь "выпрыгнуть" из плохих локальных минимумов, но усложняет точную сходимость. |
| Mini-batch Gradient Descent | Небольшая случайная подвыборка (mini-batch), например, 32 или 128 примеров. | Компромисс. Достаточно быстрый и эффективный по памяти. Является стандартом на практике. | Умеренный шум, баланс между скоростью и стабильностью сходимости. |
Почему Mini-batch SGD стал стандартом?
- Эффективность GPU: Позволяет полностью загрузить вычислительные ядра графического процессора параллельной обработкой батча.
- Стабильность: Градиент, усредненный по нескольким примерам, менее шумный, чем от одного примера, что ведет к более устойчивой сходимости.
- Скорость: Одно обновление на батч быстрее, чем проход по всему датасету (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. Пакетный градиентный спуск на больших данных практически не используется из-за непрактичных требований к памяти.
Ответ 18+ 🔞
Слушай, давай разберем эту дичь с градиентным спуском, а то у меня уже терпения ноль, ебать. Представь, что тебе надо спуститься с горы, но ты слепой и можешь только тыкать палкой, чтобы понять, куда склон. Вот эти методы — разные способы, как ты эту палку используешь.
Пакетный (Batch) — это как упрямый мужик, который хочет всё измерить дохуя точно. Он стоит, вынимает теодолит, ёпта, и меряет уклон ВСЕЙ горы целиком, глядя на каждый камень. Потом делает ОДИН, но оверточный шаг. Ебать мои старые костыли, это ж сколько времени! Памяти нужно овердохуища, и если он встал в ямку (локальный минимум), то ему похер, он считает, что дальше только вверх — и застревает. Скорость? Да хуй с горы скатится быстрее.
Стохастический (Stochastic) — это как пьяный в стельку, который спускается с горы. Он вообще не смотрит. Херак — шагнул куда попало, чих-пых тебя в сраку, упал, встал, опять шагнул. Обновляет веса после КАЖДОГО примера. Быстро? О, да, он за секунду сделает сто шагов! Но траектория у него — пиздопроебибна, зигзагами по всему склону. Шум дикий, но зато есть шанс, что он из ямки выпрыгнет, потому что его так шатает.
Мини-батч (Mini-batch) — это золотая середина, и поэтому все его и используют. Это как взять небольшую, но адекватную компанию друзей. Не одного пьяного и не всех жителей города, а, скажем, 32 человека. Ты спрашиваешь у них: «Ну что, пацаны, вниз тут?». Они вразнобой, но в целом показывают верное направление. Быстрее, чем опрашивать весь город, стабильнее, чем слушать одного алкаша. Вот это и есть стандарт, ёпта.
Почему мини-батч рулит?
- Видеокарты это любят. Им проще пачками данные жрать, чем по одному. Это как кормить слона не семечками, а целыми арбузами.
- Стабильность. Градиент усредненный, не такой манда с ушами, как в стохастике.
- Скорость. Идеальный баланс. Не будешь же ты, внатуре, ждать, пока модель весь интернет переварит за один шаг?
Смотри, как это в коде выглядит. Блоки я не трогаю, они святые.
# Batch GD — старомодный и тормозной дед
for epoch in range(num_epochs):
gradient = compute_gradient(w, entire_training_set) # Ёб твою мать, вся память кончилась!
w = w - learning_rate * gradient # Одно обновление, и ты уже седой
# Stochastic GD — гиперактивный шизоид
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 GD — адекватный работяга (ВОТ ЭТО ПРАКТИКА)
for epoch in range(num_epochs):
for batch in dataloader: # Пришла пачка данных — отработали
x_batch, y_batch = batch
gradient = compute_gradient(w, x_batch, y_batch) # Всё чётко, ясно, по делу
w = w - learning_rate * gradient
Запомни: когда в PyTorch пишешь torch.optim.SGD, то под капотом у тебя работает именно мини-батч. Пакетный спуск в наши дни — это как приехать на таксофоне в мир смартфонов. Да похуй на него.