Код-ревью Middle Оптимизаторы и обучение обновлено

Ревью: шаг обучения с клиппингом и AMP

Вопрос

Найдите ошибки в цикле обучения с mixed precision, клиппингом и расписанием.

scaler = torch.amp.GradScaler("cuda")
scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=3e-4, total_steps=total_steps)
for epoch in range(epochs):
    for x, y in train_loader:
        x, y = x.cuda(), y.cuda()
        with torch.autocast("cuda", dtype=torch.float16):
            loss = criterion(model(x), y)
        scaler.scale(loss).backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
        scaler.step(optimizer)
        scaler.update()
    scheduler.step()

Коротко

Порядок шага с AMP: zerograd, forward в autocast, scaler.scale(loss).backward(), scaler.unscale(optimizer), клиппинг, scaler.step(optimizer), scaler.update(), scheduler.step() для пошаговых расписаний. В bf16 GradScaler обычно не нужен.

Что должен найти ревьюер

  1. Ошибкастрока 8
    Нет optimizer.zero_grad(): градиенты накапливаются от шага к шагу.
  2. Ошибкастрока 9
    Клиппинг применяется к масштабированным градиентам: перед ним нужен scaler.unscale_(optimizer), иначе порог 1.0 бессмыслен.
  3. Ошибкастрока 12
    OneCycleLR рассчитан на шаг после каждого батча (total_steps), а здесь scheduler.step() раз в эпоху: lr почти не изменится.
  4. Стильстрока 3
    Не видно model.train() перед эпохой: если раньше была валидация с model.eval(), dropout и BatchNorm останутся в режиме инференса.

Разбор

Порядок шага с AMP: zero_grad, forward в autocast, scaler.scale(loss).backward(), scaler.unscale_(optimizer), клиппинг, scaler.step(optimizer), scaler.update(), scheduler.step() для пошаговых расписаний. В bf16 GradScaler обычно не нужен.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме