Примечание
Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.
Точность и полнота
Пример использования метрики точности и полноты для оценки качества выходных данных классификатора.
Точность и полнота — полезные показатели успешности прогнозирования, когда классы сильно несбалансированы. В информационном поиске точность показывает долю релевантных элементов среди фактически возвращённых, а полнота — долю возвращённых элементов среди всех элементов, которые следовало вернуть. Здесь «релевантными» считаются элементы с положительной меткой, то есть истинно положительные и ложноотрицательные.
Точность (\(P\)) определяется как число истинно положительных результатов (\(T_p\)), делённое на сумму числа истинно положительных и ложно положительных результатов (\(F_p\)).
Полнота (\(R\)) определяется как число истинно положительных результатов (\(T_p\)), делённое на сумму числа истинно положительных и ложноотрицательных результатов (\(F_n\)).
Кривая точности и полноты показывает компромисс между точностью и полнотой при различных порогах. Большая площадь под кривой означает высокие значения как полноты, так и точности. Высокая точность достигается за счёт малого числа ложно положительных результатов среди возвращённых, а высокая полнота — за счёт малого числа ложноотрицательных среди релевантных результатов. Высокие значения обеих метрик показывают, что классификатор возвращает точные результаты (высокая точность), а также большую часть всех релевантных результатов (высокая полнота).
Система с высокой полнотой, но низкой точностью возвращает большинство релевантных элементов, однако доля неверно помеченных результатов среди возвращённых велика. Система с высокой точностью, но низкой полнотой работает противоположным образом: она возвращает очень мало релевантных элементов, но большинство предсказанных меток совпадает с фактическими. Идеальная система с высокой точностью и высокой полнотой возвращает большинство релевантных элементов, причём большинство результатов помечено правильно.
Из определения точности (\(\frac{T_p}{T_p + F_p}\)) следует, что снижение порога классификатора может увеличить знаменатель за счёт увеличения числа возвращаемых результатов. Если ранее порог был установлен слишком высоко, новые результаты могут оказаться истинно положительными, что повысит точность. Если предыдущий порог был примерно оптимальным или слишком низким, дальнейшее его снижение приведёт к появлению ложно положительных результатов и снижению точности.
Полнота определяется как \(\frac{T_p}{T_p+F_n}\), где \(T_p+F_n\) не зависит от порога классификатора. Изменение порога классификатора может изменить только числитель, \(T_p\). Снижение порога классификатора может повысить полноту за счёт увеличения числа истинно положительных результатов. Также возможно, что снижение порога не изменит полноту, а точность будет колебаться. Таким образом, точность не обязательно снижается с ростом полноты.
Связь между полнотой и точностью видна на ступенчатых участках графика: на краях этих ступеней небольшое изменение порога значительно снижает точность, обеспечивая лишь незначительный прирост полноты.
Средняя точность (AP) обобщает такой график как взвешенное среднее значений точности, достигнутых при каждом пороге; в качестве веса используется прирост полноты по сравнению с предыдущим порогом:
\(\text{AP} = \sum_n (R_n - R_{n-1}) P_n\)
где \(P_n\) и \(R_n\) — точность и полнота при n-м пороге. Пара \((R_k, P_k)\) называется рабочей точкой.
AP и площадь трапеции под рабочими точками (sklearn.metrics.auc) — распространённые способы обобщения кривой точности и полноты, дающие разные результаты. Подробнее см. в Руководстве пользователя.
Кривые точности и полноты обычно используют в бинарной классификации для изучения выходных данных классификатора. Чтобы распространить кривую точности и полноты и среднюю точность на многоклассовую классификацию или классификацию с несколькими метками, необходимо бинаризовать выходные данные. Можно построить отдельную кривую для каждой метки, но также можно построить кривую точности и полноты, рассматривая каждый элемент матрицы индикаторов меток как бинарное предсказание (микроусреднение).
Примечание
# Authors: The scikit-learn developers # SPDX-License-Identifier: BSD-3-Clause
В условиях бинарной классификации
Набор данных и модель
Мы будем использовать классификатор Linear SVC для различения двух видов ирисов.
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
# Add noisy features
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape
X = np.concatenate([X, random_state.randn(n_samples, 200 * n_features)], axis=1)
# Limit to the two first classes, and split into training and test
X_train, X_test, y_train, y_test = train_test_split(
X[y < 2], y[y < 2], test_size=0.5, random_state=random_state
)
Для работы Linear SVC требуется, чтобы значения каждого признака находились в сопоставимом диапазоне. Поэтому сначала масштабируем данные с помощью StandardScaler.
from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler from sklearn.svm import LinearSVC classifier = make_pipeline(StandardScaler(), LinearSVC(random_state=random_state)) classifier.fit(X_train, y_train)
Построение кривой точности-полноты
Для построения кривой точности-полноты следует использовать PrecisionRecallDisplay. Доступны три метода:
-
для построения одной кривой:
-
from_estimator— если прогнозы ещё не вычислены -
from_predictions— если прогнозы уже вычислены
-
- для построения нескольких кривых по результатам перекрёстной проверки:
from_cv_results
Сначала построим кривую точности-полноты без прогнозов классификатора. Мы используем from_estimator, который вычислит прогнозы перед построением кривой.
from sklearn.metrics import PrecisionRecallDisplay
display = PrecisionRecallDisplay.from_estimator(
classifier, X_test, y_test, name="LinearSVC", plot_chance_level=True, despine=True
)
_ = display.ax_.set_title("2-class Precision-Recall curve")

Если у нас уже есть оценённые вероятности или оценки модели, можно использовать from_predictions.
y_score = classifier.decision_function(X_test)
display = PrecisionRecallDisplay.from_predictions(
y_test, y_score, name="LinearSVC", plot_chance_level=True, despine=True
)
_ = display.ax_.set_title("2-class Precision-Recall curve")

from_cv_results принимает результаты перекрёстной проверки из cross_validate и строит кривую точности-полноты для каждого фолда.
from sklearn.model_selection import cross_validate
classifier = make_pipeline(StandardScaler(), LinearSVC(random_state=random_state))
cv_results = cross_validate(
classifier, X_train, y_train, return_estimator=True, return_indices=True
)
display = PrecisionRecallDisplay.from_cv_results(cv_results, X_train, y_train)
_ = display.ax_.set_title("Cross-validation Precision-Recall curves")

В условиях многометочной классификации
Кривая точности-полноты не поддерживает многометочную классификацию. Однако можно выбрать способ обработки этого случая. Ниже показан такой пример.
Создание многометочных данных, обучение и прогнозирование
Мы создадим многометочный набор данных, чтобы проиллюстрировать точность-полноту в условиях многометочной классификации.
from sklearn.preprocessing import label_binarize
# Use label_binarize to be multi-label like settings
Y = label_binarize(y, classes=[0, 1, 2])
n_classes = Y.shape[1]
# Split into training and test
X_train, X_test, Y_train, Y_test = train_test_split(
X, Y, test_size=0.5, random_state=random_state
)
Для многометочного прогнозирования мы используем OneVsRestClassifier.
from sklearn.multiclass import OneVsRestClassifier
classifier = OneVsRestClassifier(
make_pipeline(StandardScaler(), LinearSVC(random_state=random_state))
)
classifier.fit(X_train, Y_train)
y_score = classifier.decision_function(X_test)
Средняя точность в условиях многометочной классификации
from sklearn.metrics import average_precision_score, precision_recall_curve
# For each class
precision = dict()
recall = dict()
average_precision = dict()
for i in range(n_classes):
precision[i], recall[i], _ = precision_recall_curve(Y_test[:, i], y_score[:, i])
average_precision[i] = average_precision_score(Y_test[:, i], y_score[:, i])
# A "micro-average": quantifying score on all classes jointly
precision["micro"], recall["micro"], _ = precision_recall_curve(
Y_test.ravel(), y_score.ravel()
)
average_precision["micro"] = average_precision_score(Y_test, y_score, average="micro")
Построение микроусреднённой кривой точности-полноты
from collections import Counter
display = PrecisionRecallDisplay(
recall=recall["micro"],
precision=precision["micro"],
average_precision=average_precision["micro"],
prevalence_pos_label=Counter(Y_test.ravel())[1] / Y_test.size,
)
display.plot(plot_chance_level=True, despine=True)
_ = display.ax_.set_title("Micro-averaged over all classes")

Построение кривой точности-полноты для каждого класса и изолиний F1
from itertools import cycle
import matplotlib.pyplot as plt
# setup plot details
colors = cycle(["navy", "turquoise", "darkorange", "cornflowerblue", "teal"])
_, ax = plt.subplots(figsize=(7, 8))
f_scores = np.linspace(0.2, 0.8, num=4)
lines, labels = [], []
for f_score in f_scores:
x = np.linspace(0.01, 1)
y = f_score * x / (2 * x - f_score)
(l,) = plt.plot(x[y >= 0], y[y >= 0], color="gray", alpha=0.2)
plt.annotate("f1={0:0.1f}".format(f_score), xy=(0.9, y[45] + 0.02))
display = PrecisionRecallDisplay(
recall=recall["micro"],
precision=precision["micro"],
average_precision=average_precision["micro"],
)
display.plot(
ax=ax, name="Micro-average precision-recall", curve_kwargs={"color": "gold"}
)
for i, color in zip(range(n_classes), colors):
display = PrecisionRecallDisplay(
recall=recall[i],
precision=precision[i],
average_precision=average_precision[i],
)
display.plot(
ax=ax,
name=f"Precision-recall for class {i}",
curve_kwargs={"color": color},
despine=True,
)
# add the legend for the iso-f1 curves
handles, labels = display.ax_.get_legend_handles_labels()
handles.extend([l])
labels.extend(["iso-f1 curves"])
# set the legend and the axes
ax.legend(handles=handles, labels=labels, loc="best")
ax.set_title("Extension of Precision-Recall curve to multi-class")
plt.show()

Общее время выполнения скрипта: (0 минут 0.547 секунды)
Связанные примеры
© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/model_selection/plot_precision_recall.html