Градиентный спуск: скатываемся в минимум

Урок напоминает, как градиентный спуск шаг за шагом ведёт параметры к минимуму потери.

Градиент — это вектор частных производных функции потерь по каждому весу; он указывает направление наискорейшего роста потери.

Идея спуска

Если градиент показывает, куда потеря растёт быстрее всего, то противоположное направление ведёт вниз — к минимуму. Поэтому правило простое: сдвигаем вес против градиента. Для одного веса: w = w - lr * dL/dw, где dL/dw — производная потери по этому весу, а lr — скорость обучения (размер шага).

Аналогия: вы в тумане на склоне холма и хотите спуститься. Вы щупаете ногой, в какую сторону спуск круче всего, и делаете шаг в обратную (вниз) сторону. Повторяете, пока не окажетесь в низине.

Спуск своими руками

Минимизируем простую функцию f(w) = (w - 3)^2. Её производная — 2*(w - 3). Стартуем с w = 0 и наблюдаем, как параметр приближается к 3.

def f(w):
    return (w - 3) ** 2

def grad(w):
    return 2 * (w - 3)

w = 0.0
lr = 0.1
for step in range(1, 21):
    g = grad(w)
    w = w - lr * g            # шаг против градиента
    if step % 4 == 0 or step == 1:
        print(f"шаг {step:>2}: w = {w:.4f}, f(w) = {f(w):.4f}")
print("Параметр сошёлся почти к w = 3 — минимуму функции.")

Вывод:

шаг  1: w = 0.6000, f(w) = 5.7600
шаг  4: w = 1.7712, f(w) = 1.5099
шаг  8: w = 2.4967, f(w) = 0.2533
шаг 12: w = 2.7938, f(w) = 0.0425
шаг 16: w = 2.9156, f(w) = 0.0071
шаг 20: w = 2.9654, f(w) = 0.0012
Параметр сошёлся почти к w = 3 — минимуму функции.

Шаги крупные вдали от минимума (там градиент большой) и мельчают у дна (градиент стремится к нулю). Это естественное «торможение» — приятное свойство градиентного спуска.

Скорость обучения решает всё

  • Слишком маленький lr — спуск идёт верно, но мучительно долго.
  • Слишком большой lr — шаги перелетают минимум, потеря скачет или вовсе расходится в бесконечность.
  • В самый раз — быстрая и стабильная сходимость. На практике lr подбирают экспериментально.

От одного веса к миллионам

В реальной сети потеря зависит от всех весов сразу. Градиент — это вектор: своя производная по каждому весу. Правило не меняется — каждый вес сдвигается против своей производной. Вопрос лишь в том, как эффективно вычислить производную по каждому из миллионов весов. Ответ — обратное распространение, тема следующего раздела.

Итог

  • Градиент указывает направление роста потери; спускаемся против него.
  • Правило шага: w = w - lr * dL/dw.
  • Шаги естественно мельчают у минимума; lr критически важен.
Проверьте себя
1. В какую сторону градиентный спуск сдвигает вес?
AПротив градиента — туда, где потеря убывает
BПо направлению градиента
CВ случайную сторону
DВсегда в сторону нуля
2. Что происходит с размером шагов по мере приближения к минимуму?
AОни растут
BОни уменьшаются, потому что градиент стремится к нулю
CОстаются постоянными
DШаги прекращаются мгновенно
3. Чем грозит слишком большая скорость обучения?
AОбучение станет идеально точным
BГрадиент станет нулевым
CШаги перелетают минимум, потеря скачет или расходится
DСеть потеряет слои