Статья Автор: Деникина Н.В., Деникин А.В.

Длина шага

Направление движения мы теперь знаем: чтобы уменьшать функцию потерь, нужно двигаться против градиента.

Но одного направления недостаточно. Нужно ещё решить, насколько сильно менять вес за один шаг.

Посмотрим на нашу точку w = 0. Производная здесь равна:

градиент = −45

Знак уже сообщает нам полезную информацию. Градиент отрицательный, значит для уменьшения ошибки вес нужно увеличивать.

Но означает ли число 45, что вес нужно сразу увеличить на 45?

Проверим:

w = 0 − (−45) = 45

Минимум находится в точке w = 3. Значит, такой шаг оказался огромным: мы проскочили минимум далеко вперёд.

Причина в том, что градиент — это не готовый шаг. Он показывает, насколько сильно функция потерь реагирует на небольшое изменение веса.

Чем больше модуль градиента, тем круче склон. Чем меньше модуль градиента, тем более пологий участок графика.

Поэтому удобно разделить две вещи:

  • градиент сообщает направление и крутизну склона;
  • скорость обучения определяет, насколько сильно мы будем реагировать на этот градиент.

Скорость обучения (learning rate, lr) — число, на которое мы умножаем градиент перед изменением веса.

Сначала вычисляем изменение веса:

Δw = −lr · градиент

а затем обновляем сам вес:

wновый = wстарый + Δw

Эти две строки часто записывают одной:

w = w − lr · градиент

Минус здесь очень важен: градиент указывает направление роста функции потерь, а нам нужно двигаться в противоположную сторону.

Посмотрим, что произойдёт при lr = 0.05.

В точке w = 0:

градиент = −45

Δw = −0.05 · (−45) = +2.25

wновый = 0 + 2.25 = 2.25

Вот теперь шаг выглядит разумно. Мы не прыгнули сразу на 45, а переместились с 0 до 2.25 — довольно близко к минимуму w = 3.

Если взять меньший lr, изменение веса будет меньше. Если взять больший — больше.

lr = 0.001  →  Δw = +0.045

lr = 0.05   →  Δw = +2.25

lr = 0.2    →  Δw = +9

То есть lr управляет размером шага.

Слишком маленький lr заставляет модель двигаться к минимуму очень медленно. Слишком большой может заставить её перескакивать через минимум и даже уходить всё дальше от него.

Универсального значения lr, подходящего для любой модели, нет. Поэтому скорость обучения является гиперпараметром: её выбирают до обучения или изменяют по специальному правилу во время обучения.

Почему шаг уменьшается возле минимума

Есть ещё одна важная особенность градиентного спуска.

Размер изменения веса равен:

|Δw| = lr · |градиент|

Поэтому при одном и том же lr размер шага зависит от самого градиента.

Далеко от минимума склон нашей функции крутой, модуль градиента большой — шаг получается большим.

Возле минимума склон становится пологим, модуль градиента уменьшается — вместе с ним автоматически уменьшается и шаг.

Посмотрим на это при lr = 0.05:

w градиент Δw = −lr · градиент новый w
0 −45 +2.25 2.25
2 −15 +0.75 2.75
2.9 −1.5 +0.075 2.975
3 0 0 3

Далеко от цели шаг большой, рядом с целью — маленький.

Это важное отличие от метода с постоянным шагом. Там длину каждого шага мы задавали заранее. Здесь она автоматически меняется вместе с крутизной функции.

В точном минимуме нашей функции:

градиент = 0

поэтому:

Δw = −lr · 0 = 0

Если алгоритм точно попал в минимум, следующий шаг ничего не изменит.

На практике обучение нейронной сети обычно не попадает в минимум идеально. Поэтому используют дополнительные условия остановки: например, ограничение числа шагов или проверку того, что функция потерь почти перестала уменьшаться.

Теперь основной цикл обучения замкнулся:

данные
  ↓
модель
  ↓
прогноз
  ↓
функция потерь
  ↓
градиент
  ↓
Δw = −lr · градиент
  ↓
новые веса
  ↓
повтор

Попробуем три разных lr

Теперь понятно, зачем нужен lr. Посмотрим, насколько сильно его значение влияет на обучение.

Запустим градиентный спуск три раза. Во всех случаях:

  • используем одну и ту же функцию потерь;
  • начинаем с w = 0;
  • ищем минимум w = 3;
  • делаем по шесть шагов.

Отличаться будет только скорость обучения.

Таблица 3. Значение веса после каждого шага.

номер шага 0 1 2 3 4 5 6
lr = 0.001 0 0.045 0.0893 0.133 0.176 0.2184 0.2601
lr = 0.05 0 2.25 2.8125 2.9531 2.9883 2.9971 2.9993
lr = 0.2 0 9 −9 27 −45 99 −189

Три значения lr дали совершенно разное поведение.

lr = 0.001 — направление правильное, но шаги слишком маленькие. Вес движется к тройке, однако очень медленно.

lr = 0.05 — шаг достаточно большой, чтобы быстро приблизиться к минимуму, но не настолько большой, чтобы потерять устойчивость. Уже через несколько шагов вес почти равен 3.

lr = 0.2 — шаг слишком большой. Алгоритм каждый раз перелетает через минимум, причём расстояние до него увеличивается. Обучение расходится.

Получается главный смысл скорости обучения:

слишком маленький lr  → обучение идёт медленно

подходящий lr         → быстро приближаемся к минимуму

слишком большой lr    → перескакиваем минимум,
                          колебания могут расти

Поэтому скорость обучения — один из самых важных параметров градиентного спуска.


lr = 0.001ползётw = 30010.04520.08930.13340.17650.21860.26lr = 0.05сходитсяw = 30012.2522.81232.95342.98852.99762.999lr = 0.2расходитсяw = 300192−9327 →4−45 →599 →6−189 →шесть шагов из w = 0; слева номер шага, стрелка — значение вышло за шкалу

Три прогона ведут себя совершенно по-разному.

  • lr = 0.001 — ползёт. Направление верное, вес растёт, но за шесть шагов он добрался только до 0.26, а нужно 3. До минимума он доберётся, но для высокой точности потребуются сотни шагов.
  • lr = 0.05 — сходится. Уже на первом шаге получаем 2.25, на третьем — 2.95, а дальше вес быстро приближается к 3. Это то поведение, которое нам нужно.
  • lr = 0.2 — расходится. Получаем 9, потом −9, затем 27, −45, 99, −189. Вес каждый раз перелетает через тройку и оказывается от неё всё дальше.

Почему выходит именно так

Разница между тремя прогонами не случайна. Для нашей простой функции её можно посчитать заранее.

Посмотрим не на сам вес, а на его отклонение от минимума. Минимум находится в точке w = 3, поэтому обозначим:

d = w − 3

Если d < 0, мы находимся слева от минимума. Если d > 0 — справа. А величина |d| показывает расстояние до минимума.

Правило обновления веса у нас такое:

новый w = w − lr · градиент

А градиент для нашей функции равен:

градиент = 15 · (w − 3)

Подставим его:

новый w = w − lr · 15 · (w − 3)

Теперь вычтем 3 из обеих сторон:

новый w − 3
=
(w − 3) − lr · 15 · (w − 3)

=
(w − 3) · (1 − 15 · lr)

Но w − 3 — это наше отклонение d. Поэтому можно записать совсем коротко:

dновое = dстарое · (1 − 15 · lr)

Вот и весь секрет поведения наших трёх прогонов.

В этой конкретной квадратичной задаче на каждом шаге отклонение от минимума умножается на одно и то же число:

1 − 15 · lr

Назовём его множителем шага. Он показывает, что произойдёт с отклонением после очередного обновления веса.

Посчитаем его для наших трёх значений lr.

Таблица 4. Отклонение от минимума d = w − 3.

  множитель 0 1 2 3 4 5 6
lr = 0.001 0.985 −3 −2.955 −2.9107 −2.867 −2.824 −2.7816 −2.7399
lr = 0.05 0.25 −3 −0.75 −0.1875 −0.0469 −0.0117 −0.0029 −0.0007
lr = 0.2 −2 −3 6 −12 24 −48 96 −192

Теперь поведение каждого прогона видно прямо из множителя.

При lr = 0.001:

множитель = 0.985

Отклонение сохраняет знак, но каждый раз становится немного меньше:

−3 → −2.955 → −2.9107 → ...

Его модуль уменьшается всего на 1.5% за один шаг. Поэтому спуск и «ползёт».

При lr = 0.05:

множитель = 0.25

Получаем:

−3 → −0.75 → −0.1875 → −0.0469 → ...

После каждого шага отклонение становится в четыре раза меньше. Знак при этом не меняется, поэтому вес приближается к минимуму всё время с одной стороны.

При lr = 0.2:

множитель = −2

Получаем:

−3 → 6 → −12 → 24 → −48 → ...

Минус заставляет отклонение менять знак: вес каждый раз перелетает через минимум. А двойка увеличивает расстояние до минимума в два раза. Поэтому спуск расходится.

Что говорит нам множитель

Теперь всё поведение нашего градиентного спуска можно определить по одному числу 1 − 15 · lr.

множитель что происходит поведение
0 < множитель < 1 модуль отклонения уменьшается, знак сохраняется сходится с одной стороны
множитель = 0 отклонение сразу становится нулём попадаем точно в минимум за один шаг
−1 < множитель < 0 модуль отклонения уменьшается, знак меняется сходится, перелетая через минимум
множитель = −1 модуль не меняется, знак меняется бесконечно колеблется
|множитель| > 1 модуль отклонения растёт расходится

Для сходимости нам нужно, чтобы модуль множителя был меньше единицы:

|1 − 15 · lr| < 1

Если считать скорость обучения положительной, получаем:

0 < lr < 2/15

или приблизительно:

0 < lr < 0.1333

Значит, в нашей конкретной задаче любое положительное lr меньше примерно 0.133 приводит к сходимости. Но разные значения дают разную скорость и разный характер движения.

Есть здесь и любопытный особый случай. Если взять:

lr = 1/15 ≈ 0.0667

то множитель станет равен нулю:

1 − 15 · 1/15 = 0

А значит:

dновое = dстарое · 0 = 0

Для нашей простой параболы такой шаг из любой стартовой точки сразу приводит точно в w = 3.

Это специальное свойство именно этой квадратичной функции. В настоящей нейронной сети поверхность функции потерь гораздо сложнее, поэтому одного идеального значения lr, которое за один шаг приводит к минимуму, обычно нет.

Теперь посмотрим на вторую важную границу. При:

lr = 2/15 ≈ 0.1333

множитель равен:

1 − 15 · 2/15 = −1

Отклонение сохраняет модуль, но на каждом шаге меняет знак. Например, из w = 0 получаем:

0 → 6 → 0 → 6 → 0 → 6 → ...

Вес не удаляется всё дальше, но и к минимуму не приближается. Поэтому значение 2/15 уже не входит в область сходимости.

Число 15 появилось из нашей конкретной функции и наших данных: это 2 · среднее квадратов километров. Если изменить данные, этот коэффициент изменится — а вместе с ним изменится и допустимый диапазон lr.

Это уже показывает одну из причин, почему универсальной скорости обучения не существует. В настоящих нейронных сетях подходящий lr зависит ещё и от архитектуры модели, масштаба данных и выбранного оптимизатора.

Как понять, что пошло не так

Во время обучения смотрят прежде всего на то, как меняется функция потерь. Полезно также следить за весами и градиентами: их поведение помогает понять, почему обучение идёт слишком медленно или начинает расходиться.


Программа печатает вес после каждого шага: 0, 9, −9, 27, −45, 99. Формула шага записана верно, градиент считается правильно, минимум в точке w = 3. В чём причина?

что происходитвероятная причина
Ошибка растётслишком большой lr
Веса скачут туда-сюда всё сильнееслишком большой lr
Веса монотонно уходят от минимумапотерян минус в правиле шага
Ошибка убывает очень медленнослишком маленький lr
Ошибка почти не меняетсяслишком маленький lr или ошибка в градиенте

Реши практическую задачу

Печать