Классический training loop
Собираем всё изученное в главный паттерн PyTorch — цикл обучения.
Training loop — повторяющаяся последовательность: предсказать, измерить ошибку, посчитать градиенты, сделать шаг по весам.
Пять шагов одной итерации
Любое обучение в PyTorch — это один и тот же ритуал из пяти действий, повторяемый много раз. Запомните его наизусть, дальше вы будете писать его постоянно:
import torch
import torch.nn as nn
model = nn.Linear(3, 1)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# 1. forward — модель делает предсказание
pred = model(X)
# 2. loss — измеряем ошибку
loss = criterion(pred, y)
# 3. zero_grad — чистим старые градиенты
optimizer.zero_grad()
# 4. backward — autograd считает новые градиенты
loss.backward()
# 5. step — оптимизатор двигает веса
optimizer.step()
Каждый шаг — это кусочек, который мы уже разбирали по отдельности. Теперь они работают вместе.
Разбор по шагам
Шаг 1, forward. model(X) прогоняет данные через слои и строит граф вычислений (помните: динамически, на лету). На выходе — предсказания.
Шаг 2, loss. criterion(pred, y) сравнивает предсказание с правильным ответом и возвращает одно число — насколько мы ошиблись. Это вершина графа.
Шаг 3, zero_grad. Обнуляем .grad всех параметров. Без этого градиенты с прошлой итерации сложатся с новыми (мы разбирали это в уроке про zero_grad) — и обучение сломается.
Шаг 4, backward. loss.backward() запускает backprop: autograd проходит граф назад и заполняет .grad каждого веса. Производные считаются автоматически.
Шаг 5, step. optimizer.step() применяет правило обновления (для SGD это w = w - lr * w.grad) и сдвигает все веса в сторону уменьшения ошибки. Это и есть градиентный спуск.
Почему именно такой порядок
Порядок не случаен. Сначала нужно посчитать loss (нельзя дифференцировать то, чего нет). zero_grad ставят перед backward, чтобы расчистить место для свежих градиентов. step — строго после backward, ведь он использует только что посчитанные .grad. Перепутаете порядок backward и step — оптимизатор сдвинет веса по устаревшим (или нулевым) градиентам.
| Шаг | Команда | Что меняет |
| forward | model(X) | строит предсказание и граф |
| loss | criterion(pred, y) | число ошибки |
| zero_grad | optimizer.zero_grad() | чистит .grad |
| backward | loss.backward() | заполняет .grad |
| step | optimizer.step() | двигает веса |
Что такое эпоха
Один проход по всем обучающим данным называют эпохой. В примере мы повторяем шаги 100 эпох — модель 100 раз увидит весь датасет и каждый раз чуть улучшит веса. Loss с эпохами должен падать; если он растёт или скачет — частые причины — слишком большой lr или забытый zero_grad.
Итог
- Цикл обучения — это ритуал из 5 шагов: forward → loss → zero_grad → backward → step.
- Порядок важен:
zero_gradперед backward,stepстрого после backward. stepдвигает веса по только что посчитанным градиентам — это градиентный спуск.- Эпоха — один проход по всем данным; за эпохи loss должен снижаться.