Что такое learning rate (скорость обучения) в нейронных сетях?

Ответ

Learning rate (LR, скорость обучения) — это, пожалуй, самый важный гиперпараметр при обучении нейронной сети. Он определяет размер шага, который делает оптимизатор (например, SGD, Adam) при обновлении весов модели на каждой итерации в направлении, противоположном градиенту функции потерь.

Аналогия: Представьте, что вы спускаетесь с холма с завязанными глазами, ощущая уклон ногами (градиент). Learning rate — это длина вашего шага.

  • Слишком большой LR (большой шаг): Вы можете перепрыгнуть через дно долины (глобальный минимум) и начать карабкаться вверх по другому склону. В обучении это приводит к расхождению — ошибка растет, веса «взрываются», модель не обучается.
  • Слишком маленький LR (крошечный шаг): Спуск будет очень медленным. Вы можете застрять в небольшой ямке (локальный минимум) или на пологом склоне (плато) и никогда не дойдете до самой низкой точки. Обучение занимает много эпох и может остановиться в неоптимальном состоянии.

Пример задания LR в PyTorch:

import torch
import torch.nn as nn
import torch.optim as optim

# Простая модель
model = nn.Linear(10, 1)

# Определяем оптимизатор и явно задаем learning rate
optimizer = optim.SGD(model.parameters(), lr=0.01)  # Классический SGD с LR=0.01
# Или адаптивный оптимизатор, который использует LR как базовую величину
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam с LR=0.001 (часто используемое значение по умолчанию)

Практические стратегии работы с LR:

  1. Поиск начального значения: Часто начинают с 0.01, 0.001 или 0.0001. Используют методы вроде learning rate range test, чтобы найти диапазон, где ошибка стабильно снижается.
  2. Использование расписаний (LR Scheduler): Динамическое изменение LR в процессе обучения — ключ к успеху.

    from torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau
    
    # Снижаем LR в 10 раз каждые 30 эпох
    scheduler1 = StepLR(optimizer, step_size=30, gamma=0.1)
    
    # Снижаем LR, когда метрика (val_loss) перестает улучшаться
    scheduler2 = ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=5)
    
    # Внутри цикла обучения:
    for epoch in range(num_epochs):
        # ... шаг обучения (optimizer.step()) ...
        scheduler1.step()           # Для StepLR
        # ИЛИ
        val_loss = ...
        scheduler2.step(val_loss)   # Для ReduceLROnPlateau
  3. Теплый старт (Warm-up): В начале обучения используют очень маленький LR, постепенно увеличивая его до основного значения. Это помогает стабилизировать обучение, особенно для больших моделей (например, трансформеров).

Ответ 18+ 🔞

Давай разберемся с этой зверюгой под названием Learning Rate, или, по-нашему, скорость обучения. Это, блядь, самый главный танец на балу гиперпараметров, ёпта. Если его настроить криво, то вся твоя модель пойдёт по пизде, хоть плачь.

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

  • Слишком большой шаг (LR завышен): Ты такой: "А, поехали!" — делаешь здоровенный прыжок, перелетаешь через самое дно долины (наш желанный минимум потерь) и начинаешь карабкаться на другой склон. В мире нейросетей это называется расхождение — ошибка растёт, веса летят в небеса, и модель превращается в тыкву. Доверия ебать ноль к такому обучению.
  • Слишком маленький шаг (LR занижен): Ты осторожничаешь как кот на раскалённой сковороде. Делаешь шажочек в миллиметр. Спуск длится овердохуища времени, и ты с высокой вероятностью застрянешь в первой попавшейся канавке (локальный минимум) или на бесконечном плато. Модель будет учиться дольше, чем я искал свои ключи вчера.

Вот как эту скорость впиндюривают в PyTorch:

import torch
import torch.nn as nn
import torch.optim as optim

# Допустим, у нас какая-то простая хуйня
model = nn.Linear(10, 1)

# Создаём оптимизатор и тычем ему LR под нос
optimizer = optim.SGD(model.parameters(), lr=0.01)  # Старый добрый SGD с LR=0.01
# Или модный адаптивный
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam, тут часто 0.001 — дефолтная мантра

А теперь, чувак, как с этим жить, чтобы не сойти с ума:

  1. Найти стартовую точку: Обычно тыкают пальцем в небо: 0.01, 0.001, 0.0001. Умные дядьки делают learning rate range test — запускают обучение на паре эпох с растущим LR и смотрят, когда ошибка начинает падать, а когда взлетает. Между этими точками — твой золотой диапазон. Подозрение ебать чувствую к любому значению, которое не проверил.

  2. Расписания (LR Scheduler) — твои лучшие друзья: Оставлять LR постоянным — это как пытаться завести машину, толкая её с горки, а потом вручную разгонять до сотни. Глупо. Нужно менять скорость по ходу дела.

    from torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau
    
    # Простое правило: каждые 30 эпох делаем LR в 10 раз меньше
    scheduler1 = StepLR(optimizer, step_size=30, gamma=0.1)
    
    # Хитрая жопа: снижаем LR, только если ошибка на валидации (val_loss) пятый раз подряд не улучшилась
    scheduler2 = ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=5)
    
    # В цикле обучения делаем так:
    for epoch in range(num_epochs):
        # ... тут ты учишь модель, делаешь optimizer.step() ...
        scheduler1.step()           # Для StepLR — просто по расписанию
        # ИЛИ
        val_loss = ... # посчитал ошибку
        scheduler2.step(val_loss)   # Для ReduceLROnPlateau — даёшь ему метрику, он сам решает
  3. Тёплый старт (Warm-up): Это когда ты не с места в карьер. В первых эпохах LR начинается с очень маленького значения (типа 0.000001) и плавно, как масло, поднимается до твоего основного значения (того самого 0.001). Это ебушки-воробушки для стабилизации обучения, особенно для этих ваших огромных трансформеров. Без этого они иногда сходят с ума сразу на старте.