Активации и функции потерь
Два недостающих кирпичика: нелинейные активации и функции потерь, по которым модель учится.
Функция потерь (loss) — число, измеряющее, насколько предсказание модели далеко от правильного ответа; именно его минимизирует обучение.
Зачем нужны активации
Если поставить друг за другом два линейных слоя без нелинейности между ними, вся сеть схлопнется в одно линейное преобразование — никакой пользы от глубины. Чтобы сеть могла выражать сложные зависимости, между слоями ставят нелинейную активацию. Самая популярная — ReLU: она оставляет положительные значения как есть, а отрицательные обнуляет.
import torch
import torch.nn as nn
relu = nn.ReLU()
x = torch.tensor([-2.0, -0.5, 0.0, 1.0, 3.0])
print(relu(x)) # tensor([0., 0., 0., 1., 3.])
| Активация | Что делает | Где применяют |
nn.ReLU | max(0, x) | скрытые слои (по умолчанию) |
nn.Sigmoid | сжимает в (0, 1) | выход бинарной классификации |
nn.Tanh | сжимает в (-1, 1) | иногда в RNN |
nn.Softmax | превращает в вероятности классов | обычно встроен в loss |
MSELoss — для регрессии
Когда модель предсказывает число (цену, температуру), ошибку меряют среднеквадратичной: nn.MSELoss усредняет квадраты разностей между предсказанием и целью. Это тот самый MSE из теории.
criterion = nn.MSELoss()
pred = torch.tensor([2.5, 0.0, 2.0])
target = torch.tensor([3.0, 0.0, 2.0])
loss = criterion(pred, target)
print(loss) # tensor(0.0833) = ((0.5^2 + 0 + 0) / 3)
CrossEntropyLoss — для классификации
Для классификации на несколько классов берут nn.CrossEntropyLoss. У неё есть два нюанса, в которых путаются почти все новички:
- На вход идут «сырые» логиты, а не вероятности.
CrossEntropyLossсама внутри применяет softmax. Поэтому softmax в конце сети ставить не нужно — будет двойное применение. - Цель — это индексы классов (целые числа), а не one-hot векторы. Для 3 классов target — это числа 0, 1 или 2.
criterion = nn.CrossEntropyLoss()
# сырые логиты модели: батч из 2 примеров, по 3 класса
logits = torch.tensor([[2.0, 0.5, 0.1],
[0.1, 0.2, 3.0]])
# правильные классы как индексы: пример 0 -> класс 0, пример 1 -> класс 2
target = torch.tensor([0, 2])
loss = criterion(logits, target)
print(loss) # одно число — насколько модель ошиблась
Запомните формулировку: «логиты на вход, индексы классов как цель, softmax внутри». Это снимает 90% ошибок с классификацией.
Как loss связан с обучением
Функция потерь — это тот самый скаляр, на котором мы вызываем .backward(). Цепочка такая: модель выдала предсказание → criterion сравнил с целью и вернул число loss → loss.backward() посчитал градиенты всех весов → оптимизатор сдвинул веса так, чтобы loss стал меньше. В следующем разделе соберём это в полный цикл.
Итог
- Активации (ReLU и др.) вносят нелинейность; без них стопка линейных слоёв бесполезна.
nn.MSELoss— для регрессии (среднеквадратичная ошибка).nn.CrossEntropyLoss— для классификации: на вход логиты, цель — индексы классов, softmax внутри.- loss — это скаляр, с которого начинается backprop и обновление весов.