Spec-Zone.ru › scikit-learn

Примечание

Перейти к концу для скачивания полного примера кода. или для запуска этого примера в вашем браузере через JupyterLite или Binder

Точность-полнота

Пример метрики точности-полноты для оценки качества выходных данных классификатора.

Точность-полнота является полезной мерой успеха прогнозирования, когда классы сильно несбалансированы. В информационном поиске точность — это мера доли релевантных элементов среди фактически возвращенных элементов, а полнота — это мера доли элементов, которые были возвращены, среди всех элементов, которые должны были быть возвращены. «Релевантность» здесь относится к элементам, которые положительно помечены, т.е. истинно положительные и ложно отрицательные.

Точность (\(P\)) определяется как количество истинно положительных (\(T_p\)) по отношению к количеству истинно положительных плюс количество ложно положительных (\(F_p\)).

\[P = \frac{T_p}{T_p+F_p}\]

Полнота (\(R\)) определяется как количество истинно положительных (\(T_p\)) по отношению к количеству истинно положительных плюс количество ложно отрицательных (\(F_n\)).

\[R = \frac{T_p}{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) являются распространенными способами обобщения кривой точность-полнота, которые приводят к различным результатам. Дополнительную информацию см. в Руководстве пользователя.

Кривые точность-полнота обычно используются в бинарной классификации для изучения выходных данных классификатора. Для расширения кривой точность-полнота и средней точности до многоклассовой или многометковой классификации необходимо бинаризировать выходные данные. Можно построить одну кривую на метку, но также можно построить кривую точность-полнота, рассматривая каждый элемент индикаторной матрицы меток как бинарное предсказание (микро-усреднение).

Примечание

См. также sklearn.metrics.average_precision_score,

sklearn.metrics.recall_score, sklearn.metrics.precision_score, sklearn.metrics.f1_score

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

В настройках бинарной классификации

Набор данных и модель

Мы будем использовать линейный классификатор 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
)

Линейный 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)
Pipeline(steps=[('standardscaler', StandardScaler()),
                ('linearsvc',
                 LinearSVC(random_state=RandomState(MT19937) at 0x7656C057E040))])
В среде Jupyter, пожалуйста, перезапустите эту ячейку, чтобы показать HTML представление, или доверьтесь блокноту.
На GitHub, HTML представление не может быть отображено, пожалуйста, попробуйте загрузить эту страницу с nbviewer.org.
Pipeline(steps=[('standardscaler', StandardScaler()),
                ('linearsvc',
                 LinearSVC(random_state=RandomState(MT19937) at 0x7656C057E040))])
StandardScaler()
LinearSVC(random_state=RandomState(MT19937) at 0x7656C057E040)


Построение кривой точность-полнота

Для построения кривой точность-полнота вы должны использовать PrecisionRecallDisplay. Действительно, доступны два метода, в зависимости от того, уже вычислили ли вы предсказания классификатора или нет.

Давайте сначала построим кривую точность-полнота без предсказаний классификатора. Мы используем 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")
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")
2-class Precision-Recall curve

В многоклассовых задачах

Кривая точность-полнота не поддерживает многоклассовые задачи. Однако можно решить, как обработать такой случай. Ниже приведен пример.

Создание данных для многоклассовой задачи, обучение и предсказание

Мы создаем набор данных для многоклассовой задачи, чтобы проиллюстрировать кривую точность-полнота в многоклассовых задачах.

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")
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", 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}", 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()
Extension of Precision-Recall curve to multi-class

Общее время выполнения скрипта: (0 минут 0,403 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_precision_recall.ipynb

Download Python source code: plot_precision_recall.py

Download zipped: plot_precision_recall.zip

Связанные примеры

Настройка стратегии повторного обучения при переборе параметров с использованием перекрестной проверки

Визуализация с помощью объектов отображения

Оценка разреженной обратной ковариации

Настройка порога решения для обучения с учетом стоимости

© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/model_selection/plot_precision_recall.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API