Receiver Operating Characteristic (ROC) Curve
Кривая рабочей характеристики приёмника (ROC) отображает долю истинно положительных результатов в зависимости от доли ложноположительных результатов при каждом пороге. Как её читать, AUC и примеры кода.
ROC-кривая (кривая ошибок классификации) показывает, насколько хорошо бинарный классификатор разделяет два класса при всех возможных порогах принятия решения. На ней по оси y отложена доля истинно положительных результатов, а по оси x — доля ложноположительных результатов. Каждая точка соответствует порогу, применённому к оценкам модели, поэтому на одном графике видны все компромиссы между обнаружением положительных примеров и ложными срабатываниями. Площадь под ней — площадь под кривой (AUC) — сводит график к одному числу, не зависящему от порога. Название метода связано с радиолокационной техникой времён Второй мировой войны, где он измерял, насколько хорошо операторы радиолокационных приёмников отличали вражеские самолёты от шумов. Позже метод распространился в медицине, психологии и машинном обучении (ML).
Как строится ROC-кривая#
Каждая точка кривой соответствует матрице ошибок, рассчитанной для одного порога:
- Доля истинно положительных результатов (TPR), также называемая полнотой или чувствительностью: TP / (TP + FN) — доля положительных примеров, которые модель распознала.
- Доля ложноположительных результатов (FPR): FP / (FP + TN) — доля отрицательных примеров, которые ошибочно распознаны как положительные. FPR равна единице минус специфичность.
При переборе порогов от высокого к низкому кривая проходит от (0, 0), где не отмечен ни один объект, до (1, 1), где отмечены все. Классификатор, который ранжирует каждый положительный пример выше каждого отрицательного, проходит через верхний левый угол. Модель со случайными догадками следует диагонали, а кривая ниже диагонали означает, что оценки инвертированы. AUC равна вероятности того, что случайно выбранный положительный пример получит более высокую оценку, чем случайно выбранный отрицательный. Поэтому 0.5 соответствует случайному угадыванию, а 1.0 — идеальному разделению. Для построения кривой нужны непрерывные оценки, например предсказанные вероятности или значения уверенности, поскольку жёсткие метки 0/1 дают только одну точку. В следующем примере классификатор логистической регрессии обучается на несбалансированном наборе данных, а кривая рассчитывается с помощью roc_curve из scikit-learn:
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, roc_curve
from sklearn.model_selection import train_test_split
# Binary task where 10% of samples are positive
X, y = make_classification(n_samples=5000, weights=[0.9], class_sep=0.8, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
# ROC analysis needs continuous scores, not hard 0/1 predictions
scores = LogisticRegression().fit(X_train, y_train).predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_test, scores)
print(f"AUC: {roc_auc_score(y_test, scores):.3f}")
# Each threshold is one point on the curve: higher recall costs more false alarms
for target in (0.80, 0.95):
i = np.argmax(tpr >= target) # first point that reaches the target TPR
print(f"Threshold {thresholds[i]:.2f}: TPR {tpr[i]:.2f}, FPR {fpr[i]:.2f}")Модель достигает AUC 0.963. При пороге 0.44 она обнаруживает 82% положительных примеров при FPR 0.01. Чтобы достичь полноты 95%, порог нужно снизить до 0.02, при этом FPR вырастет до 0.26. В этой тестовой выборке из 130 положительных и 1 120 отрицательных примеров обнаружение ещё 18 положительных обходится в 279 дополнительных ложных срабатываний.
Выбор рабочей точки#
Кривая показывает цену каждого порога, а приложение определяет, какой уровень затрат приемлем:
- Медицинский скрининг: Пропущенная опухоль обходится гораздо дороже контрольного обследования, поэтому скрининговые инструменты работают в точке с высоким TPR и допускают больше ложноположительных результатов для проверки радиологами.
- Обнаружение мошенничества: Блокировка каждого законного платежа доставляет неудобства клиенту, поэтому банки выбирают точку, которая выявляет большую часть мошенничества и удерживает FPR на уровне, приемлемом для сотрудников, проверяющих операции, и клиентов.
- Равная цена ошибок: Если обе ошибки обходятся одинаково, статистика J Юдена — TPR минус FPR — выбирает точку, наиболее удалённую над диагональю.
Модели классификации Ultralytics YOLO26 возвращают в results[0].probs.data вероятность для каждого класса — именно такие непрерывные оценки нужны для ROC-анализа. Поэтому сбор вероятностей одного класса на размеченной валидационной выборке даёт ROC-кривую «один против остальных» для этого класса и позволяет выбрать порог с учётом затрат при развёртывании.
ROC-кривая и родственные инструменты#
Кривая точности-полноты показывает точность в зависимости от полноты, а не TPR в зависимости от FPR. Поскольку TPR и FPR рассчитываются отдельно для каждого класса, ROC-кривая не меняется, если доля положительных примеров уменьшается, а точность падает. При редких положительных примерах, например при проверке мошенничества или обнаружении аномалий, даже небольшая FPR может привести к большему числу ложных срабатываний, чем истинных обнаружений. В исследовании PLOS ONE о несбалансированных наборах данных установили, что в таких условиях информативнее графики точности-полноты. Обнаружение объектов оценивают с помощью кривых точности-полноты и средней точности по классам (mAP) по схожей причине: число фоновых областей, которые считались бы истинно отрицательными, не ограничено, поэтому у FPR нет фиксированного знаменателя.
- Точность и F1-мера: Одиночные показатели, рассчитанные для одного порога, тогда как ROC-кривая и её AUC обобщают результаты для всех порогов.
- Классификация изображений с множеством классов: Для каждого класса строят ROC-кривую «один против остальных», а значения AUC для классов усредняют и получают макрооценку или оценку с весами по распространённости классов. В scikit-learn это делает
roc_auc_scoreс помощьюmulti_class="ovr".










