Типичные ошибки начинающих

Собираем в одном месте грабли, на которые наступают почти все, и как их распознать.

Большинство багов в PyTorch — не падения логики, а несовпадения форм, забытые служебные вызовы и неверные режимы. Их легко поймать, зная симптомы.

1. Несовпадение размерностей

Это ошибка номер один. Слой ждёт вход одной формы, а получает другую — или матрицы не перемножаются. Текст ошибки прямо называет ожидаемые и фактические размеры.

# mat1 and mat2 shapes cannot be multiplied (4x3 and 4x2)
# -> внутренние размерности не совпали: 3 != 4

Лечение: печатайте x.shape после каждого слоя, пока не найдёте, где форма «сломалась». Держите в голове, что вход в nn.Linear(in, out) должен иметь последнюю размерность ровно in.

2. Забытый zero_grad

Код работает, ошибок нет, но обучение странное: loss скачет или не падает. Причина — градиенты накапливаются между шагами (мы разбирали это во втором разделе).

# ПЛОХО: нет zero_grad — градиенты складываются
loss.backward()
optimizer.step()

# ХОРОШО
optimizer.zero_grad()
loss.backward()
optimizer.step()

Симптом: loss ведёт себя хаотично без видимой причины — первым делом ищите пропущенный zero_grad().

3. Перепутанный режим train/eval

Два варианта беды. Забыли model.eval() на инференсе — dropout продолжает гасить нейроны, предсказания «прыгают». Забыли вернуть model.train() после валидации — регуляризация отключена всю следующую эпоху.

Симптом: предсказания одной и той же модели на одних данных каждый раз разные → вы в режиме train с активным dropout, нужен eval().

4. Неверная функция потерь или её вход

Классика — CrossEntropyLoss: ей дали вероятности после softmax вместо логитов, или one-hot вместо индексов классов.

# ПЛОХО: лишний softmax перед CrossEntropyLoss (двойное применение)
probs = torch.softmax(logits, dim=1)
loss = criterion(probs, target)

# ХОРОШО: CrossEntropyLoss сама делает softmax
loss = criterion(logits, target)   # logits сырые, target — индексы

Симптом: модель учится подозрительно плохо или метрика не растёт — проверьте, что подаёте в loss и в каком виде target.

5. Тензоры на разных устройствах

Модель на GPU, а батч забыли перенести (раздел про GPU). Текст ошибки: «Expected all tensors to be on the same device».

Лечение: переносите и X, и y на device в начале каждой итерации.

6. Целые числа там, где нужен float

Сеть и градиенты работают с float32. Если данные пришли как int (частая история при чтении из numpy), будет ошибка типа.

# expected scalar type Float but found Long
X = X.float()    # привести признаки к float32

Чек-лист отладки

СимптомПервое подозрение
ошибка про shapes/multiplyнесовпадение размерностей слоёв
loss скачет/не падаетзабытый zero_grad() или большой lr
предсказания нестабильнызабыт model.eval()
модель плохо учитсяневерный loss или его вход
same device errorбатч не перенесён на устройство модели
expected Float but found Longнужен .float() на данных

Итог

  • Большинство багов PyTorch — формы, забытый zero_grad, неверный режим, loss и устройства.
  • Печать x.shape после слоёв находит ошибки размерностей быстрее всего.
  • Хаотичный loss → ищите zero_grad; нестабильные предсказания → нужен eval().
  • CrossEntropyLoss хочет логиты и индексы; данные часто надо приводить к .float().
Проверьте себя
1. Предсказания одной модели на одних и тех же данных каждый раз разные. В чём вероятная причина?
AСломан DataLoader
BМодель в режиме train с активным dropout — нужен model.eval()
CСлишком маленький learning rate
DНеверный тип данных
2. Ошибка «expected scalar type Float but found Long» означает, что нужно...
Aперенести тензор на GPU
Bвызвать zero_grad
Cпривести данные к float через .float()
Dуменьшить размер батча
3. Loss скачет и не снижается, хотя ошибок в коде нет. Что проверить в первую очередь?
AВерсию PyTorch
BЗабытый zero_grad() или слишком большой learning rate
CНаличие GPU
DРазмер state_dict
Поддержать проект