Learning rate: слишком большой и слишком малый шаг
Learning rate решает, выживет ли обучение: слишком большой шаг разносит спуск вразнос, слишком маленький — заставляет ползти вечность.
Learning rate (шаг обучения, η) — множитель, на который масштабируется шаг в градиентном спуске. Самый важный гиперпараметр оптимизации.
Шаг должен быть «в самый раз»
Вернёмся к спуску с горы. Если делать гигантские прыжки, легко перескочить долину и оказаться на противоположном склоне выше, чем был, — и так скакать всё выше. Если семенить миллиметровыми шажками, спустишься, но к закату. Хороший шаг — компромисс: достаточно большой, чтобы двигаться быстро, но достаточно малый, чтобы не промахиваться мимо дна. Сравним три значения lr на одной задаче.
def grad(x): return 2 * (x - 3) # минимум функции (x-3)^2 в x=3
def descend(lr, steps=8):
x = 0.0
path = [round(x, 3)]
for _ in range(steps):
x = x - lr * grad(x)
path.append(round(x, 3))
return path
print("lr=0.01 (мало) :", descend(0.01))
print("lr=0.3 (норм) :", descend(0.3))
print("lr=0.9 (велик):", descend(0.9))
Вывод:
lr=0.01 (мало) : [0.0, 0.06, 0.119, 0.176, 0.233, 0.288, 0.342, 0.396, 0.448] lr=0.3 (норм) : [0.0, 1.8, 2.52, 2.808, 2.923, 2.969, 2.988, 2.995, 2.998] lr=0.9 (велик): [0.0, 5.4, 1.08, 4.536, 1.771, 3.983, 2.214, 3.629, 2.497]
Читаем результаты
- lr = 0.01 (слишком мало): за 8 шагов добрались только до 0.45 при цели 3 — спуск ползёт, потребуются сотни итераций.
- lr = 0.3 (в самый раз): к восьмому шагу уже 2.998 — почти точное попадание в минимум. Быстро и устойчиво.
- lr = 0.9 (великоват): точка перескакивает минимум и колеблется вокруг 3 (5.4 → 1.08 → 4.54 → ...), но колебания затухают и спуск всё же сходится. Чуть больше — и затухание сменится взрывом.
Расходимость: когда шаг убивает обучение
Если шаг слишком велик, спуск не просто медленный — он расходится: значения улетают в бесконечность, и потеря растёт вместо падения. Это частая беда новичков: «модель не учится, loss стал NaN». Почти всегда виноват завышенный learning rate. Посмотрим на lr = 1.5.
def grad(x): return 2 * (x - 3)
x = 0.0
lr = 1.5 # слишком большой шаг
for step in range(1, 7):
x = x - lr * grad(x)
print(f"шаг {step}: x = {round(x, 2)}")
Вывод:
шаг 1: x = 9.0 шаг 2: x = -9.0 шаг 3: x = 27.0 шаг 4: x = -45.0 шаг 5: x = 99.0 шаг 6: x = -189.0
Вместо схождения к 3 точка всё дальше улетает от минимума, осциллируя со взрывным ростом. Это и есть расходимость.
Как выбирают learning rate
| Симптом | Причина | Что делать |
| Потеря растёт / NaN | lr слишком большой | уменьшить в 3–10 раз |
| Потеря прыгает, не падает | lr великоват | немного уменьшить |
| Потеря падает очень медленно | lr слишком маленький | увеличить |
На практике пробуют значения по логарифмической шкале (0.001, 0.01, 0.1) и смотрят на кривую потерь. Часто применяют расписание: начинают с большего шага, затем уменьшают по ходу обучения — крупные шаги в начале, аккуратная доводка в конце.
Итог
- Learning rate η — главный гиперпараметр: размер шага градиентного спуска.
- Слишком малый → спуск ползёт; слишком большой → прыгает или расходится в бесконечность.
- Растущая потеря (NaN) почти всегда означает завышенный learning rate.
- Подбирают по логарифмической шкале; часто уменьшают по ходу обучения.