Зачем она нужна
Модель бинарной классификации выдаёт число $\hat y\in(0;\,1)$ — свою вероятность того, что объект принадлежит классу 1: письмо — спам, транзакция — мошенничество, на снимке есть опухоль. Чтобы модель училась, нужна функция потерь (loss): одно число, которое тем больше, чем хуже предсказание, и которое можно дифференцировать. Бинарная кросс-энтропия (binary cross-entropy, BCE; в статистике — log loss, отрицательное лог-правдоподобие) — стандартный выбор для такой задачи.
Где она стоит:
- логистическая регрессия и выход любого бинарного классификатора — связка сигмоида + BCE;
- multi-label классификация — у каждой метки (теги фото, категории токсичности) своя сигмоида и своя BCE, метки независимы;
- градиентный бустинг —
binary:logisticв XGBoost,binaryв LightGBM,Loglossв CatBoost — это та же BCE по «сырому» счёту деревьев; - дискриминатор GAN учится с BCE: «настоящее» — 1, «сгенерированное» — 0;
- модели вознаграждения в RLHF и DPO — потеря $-\log\sigma(r_{\text{лучше}}-r_{\text{хуже}})$ — это BCE с меткой 1 для разности оценок (модель Брэдли — Терри);
- метрика — log loss на соревнованиях и в отчётах: он оценивает не только «угадал ли», но и честность вероятностей.
BCE — это $-\log$ вероятности, которую модель дала правильному ответу. Уверенный верный ответ стоит почти 0, ответ «50 на 50» — $\ln2\approx0{,}693$, уверенная ошибка — сколько угодно много. Вместе с сигмоидой градиент по логиту равен просто $\hat y-y$: без насыщения, ограничен по модулю единицей и пропорционален ошибке. BCE выпукла по весам логистической регрессии, а её минимум достигается на честных вероятностях.
Интуиция: штраф за удивление
Представьте, что модель — синоптик, который каждый день называет вероятность дождя. Если он сказал «90%» и дождь пошёл — он почти не удивлён, штраф маленький. Если сказал «10%», а дождь пошёл — он сильно ошибся и был в этом уверен; штраф должен быть большим. А если он вообще отказался от прогноза и всегда говорит «50%», его штраф каждый день один и тот же — $\ln2\approx0{,}693$.
BCE устроена именно так: потеря равна $-\ln$ вероятности того, что произошло на самом деле. Для правильного ответа $y=1$ это $-\ln\hat y$ (красная кривая), для $y=0$ — $-\ln(1-\hat y)$ (синяя). Потяните точку.
Уверенная ошибка $\hat y=0{,}1$ стоит в 22 раза больше уверенного верного ответа $\hat y=0{,}9$ ($2{,}303$ против $0{,}105$). И у потери нет потолка: при $\hat y\to0$ стена уходит в бесконечность. Ещё одно свойство логарифма: каждое уменьшение вероятности правильного ответа вдвое добавляет к потере одно и то же число $\ln2\approx0{,}693$.
Формула по косточкам
Возьмём одно слагаемое — потерю на одном объекте — и посмотрим на каждую деталь.
- $y\in\{0,1\}$
- правильный ответ (метка). Работает как переключатель: при $y=1$ второе слагаемое умножается на 0, при $y=0$ — первое;
- $\hat y\in(0;\,1)$
- предсказанная вероятность класса 1, обычно $\hat y=\sigma(z)$, где $z$ — логит (сырой выход модели);
- $1-\hat y$
- предсказанная вероятность класса 0 — две вероятности в сумме дают 1;
- $\log$
- натуральный логарифм ($\ln$): потеря измеряется в «натах»; с $\log_2$ получились бы биты;
- $-$
- минус нужен, потому что логарифм вероятности отрицателен: $\log\hat y\le0$, а потеря должна быть $\ge0$;
- $\frac1n\sum_{i=1}^{n}$
- усреднение по объектам — чтобы величина потери не зависела от размера батча.
Переключатель даёт компактную запись: пусть $p_t$ — вероятность, которую модель дала правильному классу ($p_t=\hat y$ при $y=1$ и $p_t=1-\hat y$ при $y=0$). Тогда
Вторая форма — «BCE по логитам» — понадобится для вывода градиента и для устойчивого кода. Если метки записаны как $s=\pm1$, та же потеря принимает вид логистической потери $\log(1+e^{-s z})$, где $s z$ — отступ (margin): положительный отступ означает верный ответ.
| $\hat y$ | $-\ln\hat y$ (при $y=1$) | $-\ln(1-\hat y)$ (при $y=0$) | $\partial\ell/\partial\hat y$ при $y=1$ |
|---|---|---|---|
| 0,001 | 6,908 | 0,001 | −1000 |
| 0,01 | 4,605 | 0,010 | −100 |
| 0,1 | 2,303 | 0,105 | −10 |
| 0,3 | 1,204 | 0,357 | −3,333 |
| 0,5 | 0,693 | 0,693 | −2 |
| 0,7 | 0,357 | 1,204 | −1,429 |
| 0,9 | 0,105 | 2,303 | −1,111 |
| 0,99 | 0,010 | 4,605 | −1,010 |
| 0,999 | 0,001 | 6,908 | −1,001 |
Таблица показывает асимметрию: на правильной стороне потеря быстро прижимается к нулю, на неправильной растёт как логарифм, а наклон $-1/\hat y$ при $\hat y=0{,}001$ достигает $-1000$.
Пример на четырёх объектах
Метки $y=(1;\,0;\,1;\,1)$, предсказания $\hat y=(0{,}9;\,0{,}2;\,0{,}6;\,0{,}95)$. Вероятности правильных ответов: $0{,}9$; $0{,}8$; $0{,}6$; $0{,}95$. Потери: $0{,}105$; $0{,}223$; $0{,}511$; $0{,}051$. Среднее — $\mathrm{BCE}\approx0{,}223$. Больше всех «виноват» третий объект: модель дала правильному ответу всего $0{,}6$.
Откуда она берётся: максимальное правдоподобие
BCE не придумана «на глаз» — она выводится. Пусть модель говорит: «объект относится к классу 1 с вероятностью $\hat y$». Это распределение Бернулли, и его формулу удобно записать одной строкой — снова с меткой в роли переключателя, но теперь в показателе степени:
Если объекты независимы, вероятность увидеть все метки обучающей выборки — правдоподобие (likelihood) — равна произведению. Метод максимального правдоподобия подбирает параметры модели так, чтобы это произведение было как можно больше:
Логарифм превращает произведение в сумму и не сдвигает точку максимума (он строго возрастает), минус превращает максимум в минимум, $\tfrac1n$ — в среднее. Итак, минимизировать BCE — то же самое, что максимизировать правдоподобие модели Бернулли.
На примере выше: $\mathcal L=0{,}9\cdot0{,}8\cdot0{,}6\cdot0{,}95=0{,}4104$, $-\ln0{,}4104\approx0{,}891$ — ровно сумма четырёх потерь, а деленное на 4 — та же $\mathrm{BCE}\approx0{,}223$.
Из формулы следует: $e^{-\mathrm{BCE}}=\mathcal L^{1/n}$ — среднее геометрическое вероятностей, которые модель дала правильным ответам. В примере $e^{-0{,}223}\approx0{,}800$: «в среднем модель ставит на правильный ответ 80%». Это удобный способ объяснить значение BCE не специалисту.
Почему логарифм, а не само произведение
Во-первых, произведение миллиона вероятностей, меньших 1, в компьютере становится нулём (исчезновение порядка, underflow), а сумма логарифмов — обычное число. Во-вторых, производная суммы — сумма производных: градиент по батчу складывается из вкладов объектов. В-третьих, логарифм — единственная (с точностью до множителя) непрерывная функция, превращающая независимость (умножение вероятностей) в сложение потерь, — та же причина, по которой он стоит в определении информации.
Взгляд теории информации: удивление, энтропия, KL
Тот же результат получается с другой стороны. В теории информации Клода Шеннона событие с вероятностью $p$ несёт собственную информацию $I(p)=-\log p$; её ещё называют удивлением (surprisal). Достоверное событие ($p=1$) не удивляет ($I=0$); редкое удивляет сильно; удивления независимых событий складываются. В битах ($\log_2$) событие с вероятностью $\tfrac18$ несёт 3 бита; в натах ($\ln$) один бит равен $\ln2\approx0{,}693$.
Пусть настоящий мир устроен как монетка с вероятностью «1» равной $y$, а модель верит в вероятность $\hat y$. Тогда:
Кросс-энтропия — это и есть BCE (отсюда название), причём формула работает и для «мягких» меток $y\in[0;\,1]$. Разница двух величин — расхождение Кульбака — Лейблера (KL-дивергенция):
Энтропия $H(y)$ от модели не зависит, поэтому минимизировать BCE — значит минимизировать KL, то есть «расстояние» от убеждений модели до правды. KL равна нулю только при $\hat y=y$. Для жёстких меток $y\in\{0,1\}$ энтропия равна нулю и BCE совпадает с KL.
Есть и «инженерный» смысл. Оптимальный код тратит на событие с вероятностью $p$ примерно $-\log_2p$ бит. Если кодировать события, веря в $\hat y$, а не в настоящее $y$, средняя длина сообщения равна кросс-энтропии, и перерасход по сравнению с идеалом — ровно KL. Обучая модель с BCE, мы учим её «сжимать» метки как можно экономнее.
Доказательство: KL ≥ 0 (неравенство Гиббса)
Используем $\ln t\le t-1$ (касательная к вогнутому логарифму в точке $t=1$ лежит выше графика):
Равенство в $\ln t\le t-1$ только при $t=1$, поэтому $\mathrm{KL}=0$ только при $\hat y=y$ (слагаемые с нулевым весом $y=0$ или $1-y=0$ просто пропадают).
Свойства
- Неотрицательность. $\ell\ge0$; для жёстких меток $\ell=0$ только в пределе $\hat y\to y$. С сигмоидой на выходе $\hat y$ никогда не равна точно 0 или 1, поэтому ноль недостижим.
- Неограниченность сверху. При $y=1$, $\hat y\to0$ потеря $\to+\infty$. Но в логитах рост лишь линейный: $\operatorname{softplus}(-z)\approx-z$ при $z\ll0$, и уверенная ошибка с логитом $-10$ стоит около 10, а не бесконечность.
- Ограниченный градиент по логиту. $|\partial\ell/\partial z|=|\hat y-y|<1$: каждый объект тянет модель с силой не больше 1, сколь бы сильно она ни ошибалась.
- Выпуклость по $\hat y$: $\dfrac{\partial^2\ell}{\partial\hat y^2}=\dfrac{y}{\hat y^2}+\dfrac{1-y}{(1-\hat y)^2}>0$. Выпуклость по логиту: $\dfrac{\partial^2\ell}{\partial z^2}=\hat y(1-\hat y)>0$. Отсюда — выпуклость по весам логистической регрессии (см. ниже).
- Симметрия классов: $\ell(z,y)=\ell(-z,1-y)$ — если поменять названия классов и знак логита, ничего не изменится.
- Строго собственное правило оценки (strictly proper scoring rule): если правда — монетка с вероятностью $p$, средняя потеря $H(p)+\mathrm{KL}(p\,\|\,q)$ минимальна только при прогнозе $q=p$. BCE вознаграждает честность (раздел о калибровке).
- Точка отсчёта. Модель-константа, всегда предсказывающая долю положительных $\pi$, получает $\mathrm{BCE}=H(\pi)$. Для сбалансированных классов это $\ln2\approx0{,}693$, для $\pi=0{,}1$ — $0{,}325$. Модель хуже этого порога не выучила ничего.
Выпуклость по весам логистической регрессии: гессиан
Пусть $z_i=w^\top x_i$ (сдвиг $b$ включён в $w$ через единичный признак). Градиент и гессиан средней BCE:
где $S=\operatorname{diag}\bigl(\hat y_i(1-\hat y_i)\bigr)$. Для любого вектора $v$: $v^\top\nabla^2 v=\frac1n\sum\hat y_i(1-\hat y_i)(v^\top x_i)^2\ge0$ — гессиан неотрицательно определён, функция выпукла. Значит, у логистической регрессии нет плохих локальных минимумов: любой спуск, нашедший точку с нулевым градиентом, нашёл глобальный минимум. Метки $y$ в гессиан не входят вовсе. На этом же гессиане работает метод Ньютона (IRLS) в классических реализациях.
Производная: почему σ′ сокращается
Это центральная формула страницы. Сначала производная по вероятности $\hat y$, затем — по логиту $z$, где $\hat y=\sigma(z)$.
Эта производная неудобна: при $\hat y\to0$ или $\hat y\to1$ знаменатель стремится к нулю, и градиент взрывается (в таблице выше — $-1000$ при $\hat y=0{,}001$). Но модель не выдаёт $\hat y$ напрямую — она выдаёт логит, а вероятность получается сигмоидой. Цепное правило:
Знаменатель первой дроби — в точности производная сигмоиды $\sigma'(z)=\sigma(z)\bigl(1-\sigma(z)\bigr)$ (вывод — на странице сигмоиды). Они сокращаются, и остаётся «предсказание минус правда».
Вывод по шагам через softplus
Перепишем потерю через логит. Так как $\log\sigma(z)=-\log(1+e^{-z})=-\operatorname{softplus}(-z)$ и $\log(1-\sigma(z))=\log\sigma(-z)=-\operatorname{softplus}(z)$:
Здесь использовано тождество $\operatorname{softplus}(-z)=\log(1+e^{-z})=\log\bigl(e^{-z}(e^{z}+1)\bigr)=\operatorname{softplus}(z)-z$. Производная softplus — сигмоида: $\frac{d}{dz}\log(1+e^{z})=\frac{e^{z}}{1+e^{z}}=\sigma(z)$. Значит,
Вторая производная положительна при любом $z$ — потеря строго выпукла по логиту.
Почему это не совпадение: каноническая связь
Распределение Бернулли принадлежит экспоненциальному семейству: $\log P(y)=y\,z-A(z)$, где $z=\log\frac{\hat y}{1-\hat y}$ — естественный параметр (логит), а $A(z)=\log(1+e^{z})=\operatorname{softplus}(z)$ — логарифм нормировочной константы. У любого такого семейства $A'(z)$ равна среднему, здесь $\sigma(z)$. Поэтому отрицательное лог-правдоподобие $A(z)-yz$ всегда имеет градиент «среднее − наблюдение».
Сигмоида — каноническая функция связи (точнее, обратная к ней) для Бернулли в обобщённых линейных моделях. Ровно та же картина у пар softmax + кросс-энтропия (градиент $s-y$) и «тождественный выход + MSE» для гауссова шума (градиент $\hat y-y$ для $\tfrac12(\hat y-y)^2$; у самой MSE — $2(\hat y-y)$). Поэтому формула «предсказание − правда» повторяется по всему машинному обучению.
Для весов логистической регрессии $\hat y_i=\sigma(w^\top x_i+b)$ это даёт короткие формулы, которые и используются в обучении:
Градиент $\hat y-y$ лежит в интервале $(-1;\,1)$, линейно зависит от ошибки в вероятности и не содержит множителя $\sigma'(z)$. Модель, которая уверенно ошибается, получает почти максимальный толчок; модель, которая уже права, — почти нулевой. Ровно так же (с точностью до множителя 2) выглядит градиент MSE в линейной регрессии.
Почему не MSE: насыщение и невыпуклость
Почему бы не учить классификатор квадратичной ошибкой $(\hat y-y)^2$, как в регрессии? Посчитаем градиент по логиту, когда $\hat y=\sigma(z)$:
Здесь множитель $\sigma'(z)$ уже ничем не сокращается. Если модель уверенно ошибается ($y=1$, $z\ll0$), то $\sigma'(z)\approx0$ и градиент почти нулевой: модель «не слышит» свою самую грубую ошибку. При $z=-4$ градиент BCE равен $-0{,}982$, а MSE — $-0{,}0347$, в 28 раз меньше; при $z=-6$ — уже в 203 раза. Наибольший по модулю градиент MSE, $-0{,}296$, достигается при $z=-\ln2\approx-0{,}693$ — то есть MSE сильнее всего толкает модель, которая ошибается чуть-чуть.
Вторая беда — невыпуклость. Для $y=1$ вторая производная MSE по логиту равна $-2\sigma(1-\sigma)^2(1-3\sigma)$ и отрицательна при $\sigma<\tfrac13$, то есть при $z<-\ln2$. Потеря там вогнута и почти плоская: у суммы таких слагаемых по многим объектам появляются плато и седловые области (рисунок 5). Третья беда — ограниченность: MSE не больше 1, и «очень неправ» стоит почти столько же, сколько «безнадёжно неправ».
Вывод второй производной MSE
При $y=1$: $L=(1-\sigma)^2$, $L'=-2(1-\sigma)\sigma'=-2\sigma(1-\sigma)^2$. Дифференцируем произведение, помня $\sigma'=\sigma(1-\sigma)$:
Знак определяется множителем $1-3\sigma$: при $\sigma<\tfrac13$ (то есть $z<-\ln2$) $L''<0$. Минимум $L'$ — в той же точке: $L'(-\ln2)=-2\cdot\tfrac13\cdot\tfrac49=-\tfrac{8}{27}\approx-0{,}296$.
Как метрика — пожалуйста: средний квадрат $(\hat y-y)^2$ называют оценкой Брайера (Brier score), и это тоже собственное правило оценки. Беда не в квадрате как таковом, а в обучении через сигмоиду: градиент проходит через $\sigma'$ и гаснет. Есть и вероятностная причина: MSE — это правдоподобие гауссова шума, а метки 0/1 — не гауссовы.
Ландшафт потерь в 3D
Посмотрим на потерю целиком как на функцию параметров. Возьмём логистическую регрессию с одним признаком, $\hat y=\sigma(wx+b)$, и 24 точки (по 12 каждого класса). Средняя потеря — функция двух переменных $L(w,b)$, её можно нарисовать поверхностью.
Что видно на рисунке:
- BCE — выпуклая чаша с единственным минимумом $(1{,}441;\,0{,}149)$, где $L=0{,}451$. Вдали от минимума стенки почти плоские наклонные плоскости, а не парабола: потеря растёт линейно, градиент ограничен.
- MSE — плато и складки. Её минимум $(1{,}374;\,0{,}320)$, $L=0{,}150$, лежит в узкой долине, а на краях поверхность почти горизонтальна.
- Скорость спуска. На старте норма градиента BCE равна $0{,}969$, MSE — $0{,}0174$, в 56 раз меньше. Потеря BCE отличается от минимальной меньше чем на $0{,}01$ уже на шаге 15, а останавливается спуск (норма градиента $<10^{-4}$) на шаге 63. MSE подходит к своему минимуму с той же точностью $0{,}01$ только к шагу 600, а останавливается на шаге 1150; между шагами 100 и 400 она ползёт по плато, где потеря почти не меняется ($0{,}500\to0{,}495$).
- Разные минимумы. Оптимумы двух потерь не совпадают: это разные определения «лучшей» модели. BCE ищет честные вероятности, MSE — наименьшие квадраты отклонений вероятностей от 0 и 1.
Вдали от минимума средняя BCE растёт по мере удаления почти линейно: при больших логитах $\operatorname{softplus}(-s z)\approx\max(0,-s z)$, и функция становится положительно однородной первой степени по $(w,b)$ — как конус. Поэтому градиентный спуск с постоянным шагом не «разгоняется» на крутых склонах, как на параболе MSE линейной регрессии, а идёт с ограниченной скоростью — ещё одно следствие $|\hat y-y|<1$.
BCE в обучении
Теперь двумерный случай: 60 точек двух классов, модель $\hat y=\sigma(w_1x_1+w_2x_2+b)$, полный градиентный спуск с шагом $\eta=1$ от нулевых весов:
Обратите внимание на размеры точек: крупнее всего остаются точки по «чужую» сторону границы. Их градиент $|\hat y-y|$ близок к 1, а у уверенно и верно классифицированных — к нулю. BCE сама решает, на что тратить «внимание» модели: в основном на ошибки и на точки у границы.
Линейно разделимые данные: веса уходят в бесконечность
Если классы разделяются прямой, BCE можно сделать сколь угодно малой, просто увеличивая $\|w\|$: граница остаётся на месте, а сигмоида становится всё круче. Минимума нет — есть только инфимум 0. На рисунке это видно по счётчику: на шаге 100 потеря $0{,}0205$ и $\|w\|=3{,}94$, на шаге 200 — $0{,}0133$ и $4{,}77$, на шаге 400 — $0{,}0082$ и $5{,}76$. Норма растёт примерно как логарифм числа шагов и не останавливается.
Куда сходится направление весов
На разделимых данных градиент BCE определяется точками с наименьшим отступом: вклад точки затухает как $e^{-\text{отступ}}$. Поэтому направление $w/\|w\|$ градиентного спуска сходится к направлению максимального отступа — тому же, что у жёсткого SVM (Soudry и др., 2018), а норма растёт как $\log t$. Это «неявная регуляризация» градиентного спуска. На практике бесконечный рост весов останавливают $L_2$-регуляризацией, ранней остановкой или сглаживанием меток.
Численная устойчивость: BCEWithLogits
Формула $-[y\log\hat y+(1-y)\log(1-\hat y)]$ на бумаге безупречна, но в компьютере ломается. Если сначала вычислить $\hat y=\sigma(z)$, а потом логарифм, возникают три проблемы:
- log(0). В float32 значение $\sigma(z)$ округляется ровно до 1 уже при $z>16{,}64$: тогда $1-\hat y=0$, потеря равна $\infty$, а градиент — NaN. В float64 то же самое начинается с $z>36{,}74$.
- Потеря точности до этого. Разность $1-\sigma(z)$ двух близких чисел теряет значащие цифры (катастрофическое сокращение): при $z=16$ наивный float32 даёт $15{,}942$ вместо $16$, и график идёт ступеньками.
- Обрезка (clipping) — заплатка, а не лечение. Если ограничить $\hat y$ отрезком $[\varepsilon;\,1-\varepsilon]$ с $\varepsilon=10^{-7}$ (так Keras поступает с вероятностями на входе), потеря упирается в потолок $-\ln10^{-7}\approx16{,}118$, а в float32 — даже $15{,}942$, потому что $1-10^{-7}$ округляется до $1-2^{-23}$. Хуже того, за потолком градиент обрезки равен нулю: уверенно ошибающиеся примеры перестают учить модель. PyTorch
BCELossпоступает похоже — обрезает логарифм на $-100$.
Лечение — никогда не вычислять $\hat y$ отдельно, а считать потерю прямо по логиту, через softplus и приём log-sum-exp:
Откуда эта форма
Мы уже получили $\ell=\operatorname{softplus}(z)-yz$. Осталось вычислить $\operatorname{softplus}(z)=\log(e^{0}+e^{z})$ без переполнения. Приём log-sum-exp: вынесем за скобки наибольшую экспоненту, $m=\max(0,z)$:
Один из показателей равен 0, другой равен $-|z|\le0$, поэтому экспонента никогда не переполняется, а функция log1p точно считает $\log(1+u)$ для маленьких $u$. При $|z|\to\infty$ последнее слагаемое плавно уходит в 0, и потеря асимптотически становится линейной.
pythonimport numpy as np
def sigmoid(z):
# σ(z) = (1 + tanh(z/2)) / 2 — без переполнения при любом z
return 0.5 * (1.0 + np.tanh(0.5 * np.asarray(z, dtype=float)))
def bce_with_logits(z, y, pos_weight=1.0):
"""Устойчивая BCE по логитам: y·softplus(−z) + (1 − y)·softplus(z)."""
z, y = np.asarray(z, dtype=float), np.asarray(y, dtype=float)
sp_pos = np.logaddexp(0.0, z) # softplus(z) = −log(1 − σ(z))
sp_neg = sp_pos - z # softplus(−z) = −log σ(z)
return np.mean(pos_weight * y * sp_neg + (1 - y) * sp_pos)
def bce_grad(z, y):
"""Градиент средней BCE по логитам: (σ(z) − y) / n."""
return (sigmoid(z) - y) / len(z)
z = np.array([3.0, -2.0, 0.5, 20.0])
y = np.array([1.0, 0.0, 1.0, 0.0])
print(bce_with_logits(z, y)) # 5.1624 — почти всё дал последний пример
print(bce_grad(z, y)) # ≈ [-0.0119 0.0298 -0.0944 0.25]
print(bce_with_logits(z, y, 10.0)) # 6.3384 — положительные примеры весят в 10 раз больше
# Наивно в float32: σ(20) округляется до 1, и log(1 − 1) = −inf
p = 1 / (1 + np.exp(-np.float32(20.0)))
print(-np.log(1 - p)) # inf (и RuntimeWarning)
pythonimport torch
import torch.nn as nn
z = torch.tensor([3.0, -2.0, 0.5, 20.0], requires_grad=True) # логиты
y = torch.tensor([1.0, 0.0, 1.0, 0.0])
loss = nn.BCEWithLogitsLoss()(z, y) # σ и log внутри одной устойчивой формулы
loss.backward()
print(loss.item()) # 5.1624
print(z.grad) # (σ(z) − y) / 4 ≈ [-0.0119, 0.0298, -0.0944, 0.2500]
# Плохо: сначала sigmoid, потом BCELoss. σ(20) в float32 равна 1,
# BCELoss обрезает log на −100, и последний пример стоит 100 вместо 20
p = torch.sigmoid(z.detach())
print(nn.BCELoss()(p, y).item()) # 25.1624
# Дисбаланс классов: ошибка на положительном примере в 10 раз дороже
loss_w = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([10.0]))
# Сглаживание меток: у BCEWithLogitsLoss такого параметра нет — сглаживаем сами
eps = 0.1
y_smooth = y * (1 - eps) + eps / 2 # 1 → 0.95, 0 → 0.05
Модель отдаёт логиты, потеря сама применяет сигмоиду: BCEWithLogitsLoss в PyTorch, from_logits=True в Keras, optax.sigmoid_binary_cross_entropy в JAX. Сигмоиду к выходу применяйте только тогда, когда вам нужна сама вероятность — для отчёта или порога.
Дисбаланс классов: веса и pos_weight
В реальных задачах положительных примеров часто мало: 1% мошеннических транзакций, 0,1% кликов. Обычная BCE честно учит вероятности, но вероятность редкого класса почти всюду мала, и при пороге $0{,}5$ модель почти никого не находит. Частое средство — вес положительного класса $w_+$ (в PyTorch — pos_weight):
Вес $w_+$ равносилен тому, чтобы повторить каждый положительный пример $w_+$ раз. Для правильно заданной модели оптимальные шансы умножаются на $w_+$, то есть логит сдвигается на $\ln w_+$. Модель-константа для доли положительных $\pi$ выбирает
Поэтому популярный выбор $w_+=n_{\text{neg}}/n_{\text{pos}}$ «выравнивает» классы: константа становится $0{,}5$.
Три вывода из рисунка:
- Без весов среднее предсказание равно доле класса: $0{,}091=15/165$. Это не совпадение: у логистической регрессии со сдвигом в оптимуме $\partial\mathrm{BCE}/\partial b=\frac1n\sum(\hat y_i-y_i)=0$, то есть $\sum\hat y_i=\sum y_i$.
- Вес двигает порог, а не «умнеет» модель. При $w_+=10$ сдвиг $b$ равен $1{,}91$ — близко к $\ln10\approx2{,}30$ (на конечной выборке меняется и $w$). Полнота растёт, точность падает: это та же кривая компромисса, по которой можно двигаться и порогом.
- Веса портят калибровку. Среднее $\hat y=0{,}244$ уже не равно доле $0{,}091$. Если нужны настоящие вероятности, обучайте без весов и выбирайте порог (он равен $1/(1+w_+)$ для того же решения) или пересчитайте шансы обратно: $\text{шансы}=\text{шансы}_w/w_+$.
Вывод оптимальной константы
Средняя взвешенная потеря константы $q$ при доле положительных $\pi$: $f(q)=-w_+\pi\ln q-(1-\pi)\ln(1-q)$. Приравниваем производную к нулю:
Шансы умножились ровно на $w_+$, логит сдвинулся на $\ln w_+$. При $w_+=1$ получаем $q=\pi$ — тот самый закон «среднее предсказание равно доле».
Если редкий класс ещё и «трудный», помогает Focal Loss: множитель $(1-p_t)^\gamma$ приглушает лёгкие примеры. При $\gamma=0$ она совпадает с BCE. Альтернативы — пересэмплирование и подбор порога по нужной метрике на валидации.
Сглаживание меток
При жёстких метках оптимальный логит бесконечен: чтобы потеря на положительном примере стала нулём, нужно $z\to+\infty$. Градиентный спуск честно туда идёт. На одном положительном примере с шагом $\eta=1$ от $z=0$ логит через 10, 100 и 1000 шагов равен $2{,}26$; $4{,}59$; $6{,}91$ — растёт примерно как $\ln t$ и не останавливается. Модель учится быть самоуверенной.
Сглаживание меток (label smoothing) заменяет жёсткие метки мягкими:
Теперь градиент $\sigma(z)-y_s$ обращается в ноль в конечной точке $z^*$, где $\sigma(z^*)=y_s$, а минимальная потеря равна не 0, а энтропии $H(y_s)$ (рисунок 2). При $\varepsilon=0{,}1$: $y_s=0{,}95$, $z^*=\ln19\approx2{,}944$, и тот же спуск даёт $1{,}97$; $2{,}936$; $2{,}944$ — логит останавливается. Вернитесь к рисунку 3 и сдвиньте ползунок $\varepsilon$: у кривой появится минимум, а оранжевый градиент пересечёт ноль.
| $\varepsilon$ | $y_s$ | $z^*=\ln\frac{y_s}{1-y_s}$ | $\min\ell=H(y_s)$ |
|---|---|---|---|
| 0 | 1 | +∞ | 0 |
| 0,05 | 0,975 | 3,664 | 0,117 |
| 0,1 | 0,95 | 2,944 | 0,199 |
| 0,2 | 0,9 | 2,197 | 0,325 |
Сглаживание работает как регуляризатор уверенности: веса не уходят в бесконечность, вероятности не прилипают к 0 и 1, а калибровка часто улучшается. Платить приходится тем, что оптимальный прогноз теперь не выше $1-\varepsilon/2$ (больше модель предсказывать не стремится), а «тёмное знание» о сходстве классов частично теряется (Мюллер, Корнблит, Хинтон, 2019). В Keras это параметр label_smoothing у BinaryCrossentropy, в PyTorch для BCE метки сглаживают вручную (см. код выше).
Калибровка: BCE вознаграждает честность
Модель откалибрована, если её вероятностям можно верить буквально: среди всех объектов, которым она дала около $0{,}8$, класс 1 встречается примерно в 80% случаев. Проверяют это диаграммой надёжности (reliability diagram): предсказания делят на корзины, и в каждой сравнивают среднее предсказание с долей единиц. Сводное число — ожидаемая ошибка калибровки:
Почему BCE учит калибровке? Если на объектах с одинаковыми признаками класс 1 встречается с частотой $p$, средняя потеря прогноза $q$ равна $H(p)+\mathrm{KL}(p\,\|\,q)$, и она минимальна только при $q=p$. Любое приукрашивание — и в сторону уверенности, и в сторону осторожности — стоит дороже. Точность (accuracy) так не умеет: ей безразлично, сказала модель $0{,}51$ или $0{,}99$.
На этом и основано температурное шкалирование (temperature scaling, Го и др., 2017): у обученной сети подбирают один параметр $T$ в $\hat y=\sigma(z/T)$, минимизируя BCE на валидационной выборке. Здесь $k=1/T$. Порядок предсказаний и точность при этом не меняются — меняется только честность вероятностей.
Минимизируя BCE на обучающей выборке, большая сеть может запомнить её почти идеально — это локально тот же случай «разделимых данных»: логиты растут, вероятности прилипают к 0 и 1, а на новых данных модель ошибается так же уверенно. Отсюда пара «BCE + регуляризация (weight decay, сглаживание меток, ранняя остановка)» и калибровка на отложенной выборке.
Частые ошибки
- Двойная сигмоида. Модель уже применила
sigmoid, а потеря —BCEWithLogitsLoss— применяет её ещё раз. Тогда $\sigma(\sigma(z))\in(0{,}5;\,0{,}731)$: модель в принципе не может предсказать класс 0 с вероятностью больше половины, и потеря на нём не опускается ниже $\ln2\approx0{,}693$. - Сигмоида +
BCELossвместоBCEWithLogitsLoss. Работает до первого уверенного примера, потом $\log0$, обрезка на $-100$ и нулевой градиент (раздел об устойчивости). - Метки $\pm1$ вместо $\{0,1\}$. С $y=-1$ формула BCE даёт $\log\hat y-2\log(1-\hat y)$, которая уходит в $-\infty$ при $\hat y\to0$: потеря становится отрицательной и обучение расходится. Для меток $\pm1$ есть своя форма $\log(1+e^{-s z})$.
- BCE для взаимоисключающих классов. Если ровно один из $K>2$ классов верен, нужны softmax и категориальная кросс-энтропия. Несколько сигмоид с BCE — это multi-label, где классы независимы.
- Сравнение BCE без точки отсчёта. «Потеря 0,05» звучит отлично, но при доле положительных 1% константа даёт $H(0{,}01)\approx0{,}056$ — модель почти ничему не научилась. Сравнивайте с $H(\pi)$.
- Веса классов и «вероятности». После
pos_weightвыход сигмоиды уже не вероятность (рисунок 8). Для решений с ценой ошибок подбирайте порог; для честных вероятностей — пересчитывайте или калибруйте. reduction='sum'вместо среднего. Сумма растёт с размером батча, и вместе с ней фактический шаг обучения. Меняете размер батча — меняется оптимальный темп обучения (learning rate).
Связи с другими формулами
- Сигмоида: превращает логит в $\hat y$; её производная $\sigma(1-\sigma)$ сокращается в градиенте BCE.
- Категориальная кросс-энтропия: обобщение на $K$ классов; при $K=2$ softmax + CE совпадает с сигмоидой + BCE от разности логитов $z_1-z_2$.
- Softmax: для двух классов $\operatorname{softmax}(z_1,z_2)_1=\sigma(z_1-z_2)$.
- Focal Loss: $-(1-p_t)^\gamma\log p_t$ — BCE, приглушающая лёгкие примеры; при $\gamma=0$ совпадает с BCE.
- MSE: правильная потеря для гауссова шума; с сигмоидой даёт насыщение и невыпуклость (рисунки 4 и 5).
- SGD и Adam: оптимизаторы, которые используют градиент $\frac1nX^\top(\hat y-y)$.
Итоги
1) BCE — это $-\log$ вероятности правильного ответа; метка $y$ работает как переключатель между $-\log\hat y$ и $-\log(1-\hat y)$. 2) Она выводится из максимального правдоподобия модели Бернулли и равна кросс-энтропии: $H(y)+\mathrm{KL}(y\,\|\,\hat y)$. 3) В паре с сигмоидой $\partial\ell/\partial z=\hat y-y$: множитель $\sigma'$ сокращается, градиент ограничен и не гаснет при уверенной ошибке — в отличие от MSE. 4) BCE выпукла по логиту и по весам логистической регрессии; вдали от минимума растёт линейно. 5) Считайте её по логитам: $\max(z,0)-yz+\log(1+e^{-|z|})$. 6) pos_weight сдвигает логит примерно на $\ln w_+$, сглаживание делает оптимум конечным, а минимум BCE достигается на откалиброванных вероятностях.