Зачем она нужна
Модель выдала вероятности классов — например, $(0{,}665;\,0{,}245;\,0{,}090)$ для «кошка», «собака», «птица», — а на картинке кошка. Насколько это хорошо? Нужно одно число, которое тем меньше, чем больше вероятность правильного ответа, и которое можно минимизировать градиентным спуском. Стандартный ответ — категориальная кросс-энтропия (categorical cross-entropy, CE): здесь $\mathrm{CE}=-\ln0{,}665\approx0{,}408$.
Где она встречается:
- обучение многоклассовых классификаторов — от логистической регрессии до ResNet и ViT: последний слой выдаёт логиты, softmax превращает их в вероятности, CE оценивает ответ;
- языковые модели — предобучение GPT, LLaMA, Qwen — это минимизация CE следующего токена: классы — токены словаря, а $e^{\mathrm{CE}}$ — знаменитая перплексия;
- дистилляция знаний — ученик минимизирует CE до «мягких» вероятностей учителя;
- статистика — минимизация CE равносильна методу максимального правдоподобия для категориального распределения;
- теория информации — CE равна средней длине кода, если кодировать данные по модели $q$, а приходят они из распределения $p$.
$\mathrm{CE}=-\sum_k y_k\ln\hat y_k$; для one-hot метки это минус логарифм вероятности правильного класса. Уверенная ошибка стоит дорого: $-\ln0{,}1\approx2{,}303$ против $-\ln0{,}9\approx0{,}105$. В паре с softmax градиент по логитам — просто $s-y$, без насыщения. Кросс-энтропия = энтропия + KL-дивергенция, а $e^{\mathrm{CE}}$ — перплексия.
Интуиция: штраф за удивление
Пусть модель заранее объявляет вероятности, а потом узнаёт правильный ответ. Если правильному классу она дала вероятность $p$, её «удивление» равно $-\ln p$: при $p=1$ удивления нет, при $p=0{,}5$ оно равно $\ln2\approx0{,}693$, а при $p\to0$ растёт до бесконечности. Кросс-энтропия — среднее удивление модели на данных.
Почему именно логарифм? Во-первых, он превращает произведение вероятностей независимых примеров в сумму. Во-вторых, он поощряет честность: среди штрафов, зависящих только от вероятности, которую модель дала случившемуся исходу, при трёх и более исходах лишь логарифмический (с точностью до положительного множителя и константы) минимален в среднем тогда, когда модель называет свои истинные вероятности.
Уверенная ошибка ($p=0{,}1$) стоит в 22 раза больше уверенного правильного ответа ($p=0{,}9$). При $p=0{,}01$ штраф уже $4{,}605$ и растёт без предела, а квадратичная ошибка $(1-p)^2$ так и остаётся меньше единицы ($0{,}980$). Производная $-1/p$ неограниченно растёт по модулю при $p\to0$: чем хуже ответ, тем сильнее толчок.
Формула по косточкам
- $y=(y_1,\dots,y_K)$
- истинное распределение; обычно one-hot: $y_c=1$ для правильного класса $c$ и $0$ для остальных;
- $\hat y_k$
- предсказанная вероятность класса $k$, как правило $\hat y=s=\operatorname{softmax}(z)$;
- $\ln$
- натуральный логарифм: CE измеряется в натах (nats); с $\log_2$ — в битах, $1$ нат $\approx1{,}443$ бита;
- $-$
- логарифм вероятности отрицателен, минус делает потерю неотрицательной.
Для one-hot метки в сумме выживает одно слагаемое. Подставив $s=\operatorname{softmax}(z)$, получаем формулу прямо через логиты:
Последняя форма — главная на практике: потеря считается без явного softmax. Для батча из $N$ примеров потери усредняют:
Пример шпаргалки — логиты $(2;\,1;\,0)$, правильный класс первый:
| $k$ | $z_k$ | $s_k$ | $y_k$ | $-y_k\ln s_k$ | $s_k-y_k$ |
|---|---|---|---|---|---|
| 1 | 2 | 0,665 | 1 | 0,408 | −0,335 |
| 2 | 1 | 0,245 | 0 | 0 | 0,245 |
| 3 | 0 | 0,090 | 0 | 0 | 0,090 |
| Σ | 1 | 1 | 0,408 | 0 |
Итог: $\mathrm{CE}\approx0{,}408$, градиент $s-y\approx(-0{,}335;\,0{,}245;\,0{,}090)$. Если бы правильным был третий класс, потеря была бы $-\ln0{,}090\approx2{,}408$ — модель уверенно ошиблась.
CE и максимальное правдоподобие
Пусть модель с параметрами $\theta$ назначает классу $c_n$ вероятность $q_\theta(c_n\mid x_n)$. Правдоподобие выборки — произведение $\prod_n q_\theta(c_n\mid x_n)$. Логарифм превращает произведение в сумму, а смена знака — максимизацию в минимизацию:
Минимизировать среднюю CE — то же, что искать оценку максимального правдоподобия для категориального распределения. Поэтому CE — не произвольный выбор, а «родная» потеря вероятностного классификатора.
Энтропия, кросс-энтропия и KL-дивергенция
Название пришло из теории информации. Пусть события приходят из распределения $p$, а мы кодируем их, исходя из модели $q$. Тогда:
$H(p)$ — неустранимая неопределённость самих данных (энтропия), $\mathrm{KL}(p\,\|\,q)\ge0$ — штраф за то, что модель $q$ отличается от правды (неравенство Гиббса; равенство только при $q=p$). Поэтому минимум кросс-энтропии по $q$ достигается при $q=p$ и равен $H(p)$. Для one-hot метки $H(y)=0$, и CE совпадает с KL-дивергенцией.
Почему KL ≥ 0
По неравенству Йенсена для вогнутого логарифма (суммы — по $k$ с $p_k>0$):
Равенство — только когда $q_k=p_k$ для всех $k$.
С $\log_2$ кросс-энтропия измеряется в битах — это буквально среднее число бит на событие при оптимальном коде, построенном по $q$. В машинном обучении берут натуральный логарифм: производные проще, а минимум тот же. Перевод: $1$ нат $=1/\ln2\approx1{,}443$ бита.
Производная: почему softmax + CE дают s − y
Посчитаем градиент потери по логитам. Можно идти через матрицу Якоби softmax, но короче — через форму $\mathrm{CE}=\operatorname{LSE}(z)-z_c$: производная LSE — это softmax (см. страницу softmax), а производная $z_c$ по $z_k$ равна $y_k$.
Вывод через матрицу Якоби (цепное правило)
Производная по вероятностям: $\partial\,\mathrm{CE}/\partial s_i=-y_i/s_i$. Якобиан softmax: $\partial s_i/\partial z_k=s_i(\delta_{ik}-s_k)$. По цепному правилу:
На последнем шаге использовано $\sum_i y_i=1$. Множители $s_i$ из якобиана сократились со знаменателями $1/s_i$ из логарифма — вся матрица схлопнулась в разность. Формула верна для любой цели $y$ с суммой 1, не только one-hot (например, при сглаживании меток).
У этой формулы три важных следствия:
- градиент ограничен: каждая компонента $s_k-y_k$ лежит в $(-1;\,1)$, а их сумма равна 0 — правильный логит тянется вверх ровно настолько, насколько остальные в сумме тянутся вниз;
- нет насыщения на ошибке: если модель уверенно ошибается ($s_c\to0$), градиент по правильному логиту стремится к $-1$, а не к нулю. Сравните с MSE поверх softmax, где множители из якобиана гасят градиент как раз тогда, когда ошибка велика (раздел про CE и MSE);
- затухание на успехе: когда $s\to y$, градиент стремится к 0 — хорошо выученные примеры почти не влияют на обучение.
Вторая производная: CE выпукла по логитам
Продифференцируем $s_k-y_k$ ещё раз: гессиан CE по логитам равен якобиану softmax, $\nabla^2_z\,\mathrm{CE}=\operatorname{diag}(s)-ss^\top$. Эта матрица неотрицательно определена, поэтому CE — выпуклая функция логитов, а у softmax-регрессии $z=Wx+b$ потеря выпукла по $(W,b)$: плохих локальных минимумов нет. В направлении $\mathbf 1$ матрица вырождена — сдвиг всех логитов не меняет потерю.
Ландшафт потерь в 3D
Зафиксируем третий логит $z_3=0$ и нарисуем потерю как функцию двух других. Для правильного класса 1:
Где $z_1$ намного больше и $z_2$, и нуля, обе экспоненты под логарифмом малы, и потеря близка к 0. Где первый класс проигрывает, потеря растёт почти линейно — примерно как $\max(z_2,0)-z_1$. Получается выпуклая «долина», которая плавно уходит вниз, но нуля не достигает.
Для one-hot цели нижняя грань CE равна 0, но достигается она только при бесконечном отрыве правильного логита. Если модель может разделить обучающие данные идеально, CE продолжает уменьшаться за счёт роста логитов, и веса уходят в бесконечность. Это лечат регуляризацией весов, ранней остановкой и сглаживанием меток.
Сглаживание меток
Сглаживание меток (label smoothing) заменяет one-hot цель смесью с равномерным распределением:
Правильный класс получает $1-\varepsilon+\varepsilon/K$, каждый из остальных — $\varepsilon/K$. Теперь у потери есть настоящий минимум: градиент $s-y^{\mathrm{LS}}$ обнуляется, когда $s=y^{\mathrm{LS}}$. Если все неправильные логиты равны, а правильный опережает их на $m$, оптимальный отрыв конечен:
Сглаживание меток (Сегеди и др., 2016, Inception-v3) ограничивает рост логитов и обычно улучшает калибровку; оно стоит, например, в оригинальном Transformer с $\varepsilon=0{,}1$. Цена — модель больше никогда не уверена на 100%, а информация о сходстве классов в её логитах частично стирается, что может мешать дистилляции (Мюллер и др., 2019).
CE против MSE: почему классификаторы учат на кросс-энтропии
Почему бы не обучать классификатор квадратичной ошибкой $\|s-y\|^2$ между вероятностями и one-hot меткой? Сравним градиенты по логитам:
У MSE в градиенте стоит множитель $s$ из матрицы Якоби. Если модель уверенно ошибается — почти вся масса у одного неправильного класса, — градиент почти обнуляется: для маленьких $s_k$ мал множитель $s_k$, а для неправильного класса-фаворита почти нулевой оказывается скобка. Модель «не слышит» собственную грубую ошибку. В градиенте CE такого множителя нет.
Квадратичная ошибка между вероятностями и меткой называется оценкой Брайера (Brier score) и полезна как метрика калибровки. Для обучения классификаторов почти всегда берут CE: она выпукла по логитам и не насыщается на ошибках.
Языковые модели и перплексия
Языковая модель на каждой позиции $t$ предсказывает распределение следующего токена по словарю из $V$ токенов (десятки и сотни тысяч). Это классификация на $V$ классов, и потеря — средняя кросс-энтропия по позициям:
Перплексия — экспонента от CE, то есть среднее геометрическое величин $1/p_t$. Её читают как «эффективное число вариантов»: модель, которая всегда равномерно распределяет вероятность между $k$ токенами, причём правильный всегда среди них, имеет перплексию ровно $k$. Модель, ничего не знающая о языке (равномерное распределение по словарю), имеет $\mathcal L=\ln V$ и $\mathrm{PPL}=V$.
Перплексия зависит от токенизатора: на одном и том же тексте модель с более крупными токенами делает меньше предсказаний, и каждое труднее. Сравнивать можно модели с одинаковым словарём на одних и тех же данных — или переходить к битам на символ или байт.
В коде
Главное правило — считать CE по логитам через log-softmax: $\mathrm{CE}=\operatorname{LSE}(z)-z_c$. Путь «softmax, потом логарифм» на уверенных ошибках даёт $\ln0=-\infty$: для логитов $(0;\,800;\,0)$ и правильного первого класса наивный код возвращает inf, а устойчивый — точный ответ $800$.
pythonimport numpy as np
np.set_printoptions(precision=3)
def log_softmax(z):
z = z - z.max(axis=-1, keepdims=True) # устойчивость: max-трюк
return z - np.log(np.exp(z).sum(axis=-1, keepdims=True))
def cross_entropy(logits, y):
"""Средняя CE по батчу. logits: (N, K), y: (N,) — номера классов."""
logp = log_softmax(logits)
return -logp[np.arange(len(y)), y].mean()
def cross_entropy_grad(logits, y):
# dCE/dz = (softmax(z) − onehot(y)) / N
s = np.exp(log_softmax(logits))
s[np.arange(len(y)), y] -= 1
return s / len(y)
z = np.array([[2.0, 1.0, 0.0]])
print(cross_entropy(z, np.array([0]))) # ≈ 0.4076
print(cross_entropy(z, np.array([2]))) # ≈ 2.4076 — уверенная ошибка
print(cross_entropy_grad(z, np.array([0]))) # [[-0.335 0.245 0.09 ]]
print(cross_entropy(z + 1000, np.array([0]))) # ≈ 0.4076 — без переполнения
pythonimport torch
import torch.nn.functional as F
logits = torch.tensor([[2.0, 1.0, 0.0]], requires_grad=True)
target = torch.tensor([0]) # номер класса, а не one-hot
loss = F.cross_entropy(logits, target) # tensor(0.4076): log_softmax + NLL
loss.backward()
print(logits.grad) # tensor([[-0.3348, 0.2447, 0.0900]])
F.cross_entropy(logits, target, label_smoothing=0.1) # tensor(0.5076)
# Языковая модель: логиты (B, T, V), токены (B, T)
B, T, V = 2, 5, 50000
lm_logits = torch.randn(B, T, V)
tokens = torch.randint(0, V, (B, T))
loss = F.cross_entropy(lm_logits.reshape(-1, V), tokens.reshape(-1))
print(torch.exp(loss)) # перплексия: порядка V для случайных логитов
F.cross_entropy / nn.CrossEntropyLoss принимает логиты (без softmax!) и номера классов типа long — или вероятности той же формы, что и логиты. Полезные параметры: label_smoothing, weight (веса классов при дисбалансе), ignore_index (например, паддинг). Классы должны стоять во втором измерении, поэтому логиты формы $(B,T,V)$ проще всего превратить в $(BT,V)$ через reshape.
Частые ошибки
- Softmax перед
CrossEntropyLoss— двойной softmax: вероятности зажаты, потеря не опускается до нуля, градиенты искажены. Подавайте логиты. np.log(softmax(z))вместо log-softmax — на уверенной ошибке вероятность округляется до 0, потеря становитсяinf, градиент — NaN. «Заплатка»clip(p, 1e-7, 1)спасает от бесконечности, но обрезает градиент; правильнее LSE.- Путаница one-hot и номеров классов. В Keras это разные функции:
categorical_crossentropyждёт one-hot,sparse_categorical_crossentropy— номера. В PyTorch номера должны иметь типlong, а вероятностные цели — ту же форму, что логиты. - Сумма вместо среднего. С
reduction='sum'потеря и градиент растут с размером батча, и подобранный темп обучения перестаёт подходить. - Дисбаланс классов без внимания. CE усредняет по примерам, поэтому редкий класс почти не влияет на градиент. Помогают веса классов (
weight) или Focal Loss. - Несопоставимые числа: потери в натах и битах, перплексии моделей с разными токенизаторами.
Связи с другими формулами
- Softmax: даёт вероятности $s$; вместе с CE — градиент $s-y$, а $\mathrm{CE}=\operatorname{LSE}(z)-z_c$.
- BCE: случай $K=2$ с одним выходом: $-\bigl[y\ln\hat y+(1-y)\ln(1-\hat y)\bigr]$.
- Сигмоида: для двух классов softmax сводится к сигмоиде, и CE превращается в BCE.
- Focal Loss: $-(1-p_t)^\gamma\ln p_t$ — кросс-энтропия, ослабленная на лёгких примерах.
- MSE: поверх softmax насыщается на уверенных ошибках (см. раздел о сравнении).
- Adam: оптимизатор, которым обычно минимизируют CE в глубоких сетях.
Итоги
1) Для one-hot метки $\mathrm{CE}=-\ln s_c$ — удивление модели правильным ответом; среднее по данным — минус логарифм правдоподобия, делённый на $N$. 2) $H(p,q)=H(p)+\mathrm{KL}(p\,\|\,q)$: минимум по $q$ — при $q=p$. 3) С softmax градиент по логитам равен $s-y$: он ограничен, не насыщается на ошибках и исчезает на успехе; CE выпукла по логитам. 4) На one-hot целях минимум недостижим — логиты растут; сглаживание меток делает оптимум конечным. 5) Считайте CE по логитам через log-sum-exp; $e^{\mathrm{CE}}$ — перплексия.