Як побудувати криву ROC в Python


88

Я намагаюся побудувати криву ROC для оцінки точності моделі прогнозування, яку я розробив у Python, використовуючи пакети логістичної регресії. Я розрахував істинний позитивний показник, а також хибнопозитивний показник; однак я не можу зрозуміти, як правильно скласти їх, використовуючи matplotlibта обчислити значення AUC. Як я міг це зробити?

Відповіді:


110

Ось два способи, які ви можете спробувати, припустивши, що ви modelє провісником sklearn:

import sklearn.metrics as metrics
# calculate the fpr and tpr for all thresholds of the classification
probs = model.predict_proba(X_test)
preds = probs[:,1]
fpr, tpr, threshold = metrics.roc_curve(y_test, preds)
roc_auc = metrics.auc(fpr, tpr)

# method I: plt
import matplotlib.pyplot as plt
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()

# method II: ggplot
from ggplot import *
df = pd.DataFrame(dict(fpr = fpr, tpr = tpr))
ggplot(df, aes(x = 'fpr', y = 'tpr')) + geom_line() + geom_abline(linetype = 'dashed')

або спробувати

ggplot(df, aes(x = 'fpr', ymin = 0, ymax = 'tpr')) + geom_line(aes(y = 'tpr')) + geom_area(alpha = 0.2) + ggtitle("ROC Curve w/ AUC = %s" % str(roc_auc)) 

Отже, "preds" - це в основному ваші оцінки predict_proba, а "model" - ваш класифікатор?
Кріс Нільсен,

@ChrisNielsen preds is y hat; так, модель - це навчений класифікатор
uniquegino

Що таке all thresholds, як вони обчислюються?
mrgloom

@mrgloom вони вибираються автоматично sklearn.metrics.roc_curve
erobertc

89

Це найпростіший спосіб побудови кривої ROC з урахуванням набору основних позначок істини та передбачених ймовірностей. Найкраще, це побудова кривої ROC для ВСІХ класів, тому ви також отримуєте кілька акуратних кривих

import scikitplot as skplt
import matplotlib.pyplot as plt

y_true = # ground truth labels
y_probas = # predicted probabilities generated by sklearn classifier
skplt.metrics.plot_roc_curve(y_true, y_probas)
plt.show()

Ось зразок кривої, згенерований plot_roc_curve. Я використав набір зразків цифр від scikit-learn, тому існує 10 класів. Зверніть увагу, що для кожного класу побудована одна крива ROC.

Криві РПЦ

Застереження: Зверніть увагу, що тут використовується бібліотека scikit-plot , яку я створив.


3
Як розрахувати y_true ,y_probas ?
Md. Rezwanul Haque

3
Reii Nakano - Ви геній під виглядом ангела. Ви зробили мій день. Цей пакет настільки простий, але при цьому дуже ефективний. Ви маєте мою повну повагу. Лише невелика примітка щодо вашого фрагмента коду вище; рядок до останнього не повинен читати skplt.metrics.plot_roc_curve(y_true, y_probas):? Велике спасибі.
сальву

1
Це слід було вибрати як правильну відповідь! Дуже корисний пакет
Шріватса

24
У мене проблеми зі спробою використовувати пакет. Кожного разу, коли я намагаюся подати криву сюжету, це говорить мені, що у мене "занадто багато індексів". Я годую свій y_test і, перед цим. Я здатний враховувати свої прогнози. Але не можу отримати змову через цю помилку. Це пов'язано з версією python, яку я запускаю?
Herc01,

4
Мені довелося змінити дані y_pred, щоб вони мали розмір Nx1, а не просто список: y_pred.reshape (len (y_pred), 1). Зараз я замість цього отримую помилку "IndexError: індекс 1 виходить за межі осі 1 з розміром 1", але малюється цифра, яка, я думаю, полягає в тому, що код очікує, що двійковий класифікатор надає вектор Nx2 з кожною ймовірністю класу
Vidar

42

Зовсім незрозуміло, в чому тут проблема, але якщо у вас є масив true_positive_rateі масив false_positive_rate, то побудова кривої ROC та отримання AUC прості, як:

import matplotlib.pyplot as plt
import numpy as np

x = # false_positive_rate
y = # true_positive_rate 

# This is the ROC curve
plt.plot(x,y)
plt.show() 

# This is the AUC
auc = np.trapz(y,x)

8
ця відповідь була б набагато кращою, якби в коді були одна лінія FPR, TPR.
Ерін

12
fpr, tpr, порог = метрики .roc_curve (y_test, preds)
Ерін

що тут означає "метрика"? що це саме?
dekio

1
@dekio 'метрики' тут від sklearn: від метрик імпорту sklearn
Baptiste Pouthier

39

Крива AUC для двійкової класифікації з використанням matplotlib

from sklearn import svm, datasets
from sklearn import metrics
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import matplotlib.pyplot as plt

Завантажити набір даних про рак молочної залози

breast_cancer = load_breast_cancer()

X = breast_cancer.data
y = breast_cancer.target

Розділіть набір даних

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.33, random_state=44)

Модель

clf = LogisticRegression(penalty='l2', C=0.1)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

Точність

print("Accuracy", metrics.accuracy_score(y_test, y_pred))

Крива AUC

y_pred_proba = clf.predict_proba(X_test)[::,1]
fpr, tpr, _ = metrics.roc_curve(y_test,  y_pred_proba)
auc = metrics.roc_auc_score(y_test, y_pred_proba)
plt.plot(fpr,tpr,label="data 1, auc="+str(auc))
plt.legend(loc=4)
plt.show()

Крива AUC


19

Ось код python для обчислення кривої ROC (як графік розсіювання):

import matplotlib.pyplot as plt
import numpy as np

score = np.array([0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1])
y = np.array([1,1,0, 1, 1, 1, 0, 0, 1, 0, 1,0, 1, 0, 0, 0, 1 , 0, 1, 0])

# false positive rate
fpr = []
# true positive rate
tpr = []
# Iterate thresholds from 0.0, 0.01, ... 1.0
thresholds = np.arange(0.0, 1.01, .01)

# get number of positive and negative examples in the dataset
P = sum(y)
N = len(y) - P

# iterate through all thresholds and determine fraction of true positives
# and false positives found at this threshold
for thresh in thresholds:
    FP=0
    TP=0
    for i in range(len(score)):
        if (score[i] > thresh):
            if y[i] == 1:
                TP = TP + 1
            if y[i] == 0:
                FP = FP + 1
    fpr.append(FP/float(N))
    tpr.append(TP/float(P))

plt.scatter(fpr, tpr)
plt.show()

Ви також використовували той самий індекс зовнішнього циклу "i" у внутрішньому циклі.
Алі Єшилканат

Посилання на номер 404.
luckydonald

@Mona, дякую, що вказали, як працює алгоритм.
user3225309

9
from sklearn import metrics
import numpy as np
import matplotlib.pyplot as plt

y_true = # true labels
y_probas = # predicted results
fpr, tpr, thresholds = metrics.roc_curve(y_true, y_probas, pos_label=0)

# Print ROC curve
plt.plot(fpr,tpr)
plt.show() 

# Print AUC
auc = np.trapz(tpr,fpr)
print('AUC:', auc)

2
Як розрахувати y_true = # true labels, y_probas = # predicted results?
Md. Rezwanul Haque

2
Якщо у вас є основна правда, y_true - це ваша основна правда (ярлик), y_probas - прогнозовані результати вашої моделі
Cherry Wu

6

Попередні відповіді припускають, що ви дійсно самі розрахували TP / Sens. Погано робити це вручну, легко помилитися з обчисленнями, скоріше для цього використовуйте бібліотечну функцію.

Функція plot_roc у scikit_lean робить саме те, що вам потрібно: http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html

Суттєвою частиною коду є:

  for i in range(n_classes):
      fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
      roc_auc[i] = auc(fpr[i], tpr[i])

Як розрахувати y_score?
Saeed

6

На основі кількох коментарів stackoverflow, документації scikit-learn та деяких інших, я створив пакет python для побудови кривої ROC (та іншої метрики) дуже простим способом.

Щоб встановити пакет: pip install plot-metric (більше інформації в кінці допису)

Щоб побудувати криву ROC (приклад подано з документації):

Бінарна класифікація

Давайте завантажимо простий набір даних і складемо набір поїздів і тестів:

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
X, y = make_classification(n_samples=1000, n_classes=2, weights=[1,1], random_state=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=2)

Навчіть класифікатор та передбачіть набір тестів:

from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(n_estimators=50, random_state=23)
model = clf.fit(X_train, y_train)

# Use predict_proba to predict probability of the class
y_pred = clf.predict_proba(X_test)[:,1]

Тепер ви можете використовувати plot_metric для побудови кривої ROC:

from plot_metric.functions import BinaryClassification
# Visualisation with plot_metric
bc = BinaryClassification(y_test, y_pred, labels=["Class 1", "Class 2"])

# Figures
plt.figure(figsize=(5,5))
bc.plot_roc_curve()
plt.show()

Результат: Крива ROC

Ви можете знайти більше прикладів на github та документацію до пакету:


Я спробував це, і це приємно, але, здається, це не працює, лише якщо мітки класифікації були 0 або 1, але якщо у мене є 1 і 2, це не працює (як мітки), чи знаєте ви, як це вирішити? а також здається неможливим редагувати графік (як легенда)
Reut


4

Я зробив просту функцію, включену в пакет для кривої ROC. Я щойно почав практикувати машинне навчання, тому, будь ласка, також повідомте мені, чи є у цього коду якісь проблеми!

Подивіться файл github readme, щоб отримати докладнішу інформацію! :)

https://github.com/bc123456/ROC

from sklearn.metrics import confusion_matrix, accuracy_score, roc_auc_score, roc_curve
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

def plot_ROC(y_train_true, y_train_prob, y_test_true, y_test_prob):
    '''
    a funciton to plot the ROC curve for train labels and test labels.
    Use the best threshold found in train set to classify items in test set.
    '''
    fpr_train, tpr_train, thresholds_train = roc_curve(y_train_true, y_train_prob, pos_label =True)
    sum_sensitivity_specificity_train = tpr_train + (1-fpr_train)
    best_threshold_id_train = np.argmax(sum_sensitivity_specificity_train)
    best_threshold = thresholds_train[best_threshold_id_train]
    best_fpr_train = fpr_train[best_threshold_id_train]
    best_tpr_train = tpr_train[best_threshold_id_train]
    y_train = y_train_prob > best_threshold

    cm_train = confusion_matrix(y_train_true, y_train)
    acc_train = accuracy_score(y_train_true, y_train)
    auc_train = roc_auc_score(y_train_true, y_train)

    print 'Train Accuracy: %s ' %acc_train
    print 'Train AUC: %s ' %auc_train
    print 'Train Confusion Matrix:'
    print cm_train

    fig = plt.figure(figsize=(10,5))
    ax = fig.add_subplot(121)
    curve1 = ax.plot(fpr_train, tpr_train)
    curve2 = ax.plot([0, 1], [0, 1], color='navy', linestyle='--')
    dot = ax.plot(best_fpr_train, best_tpr_train, marker='o', color='black')
    ax.text(best_fpr_train, best_tpr_train, s = '(%.3f,%.3f)' %(best_fpr_train, best_tpr_train))
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.0])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('ROC curve (Train), AUC = %.4f'%auc_train)

    fpr_test, tpr_test, thresholds_test = roc_curve(y_test_true, y_test_prob, pos_label =True)

    y_test = y_test_prob > best_threshold

    cm_test = confusion_matrix(y_test_true, y_test)
    acc_test = accuracy_score(y_test_true, y_test)
    auc_test = roc_auc_score(y_test_true, y_test)

    print 'Test Accuracy: %s ' %acc_test
    print 'Test AUC: %s ' %auc_test
    print 'Test Confusion Matrix:'
    print cm_test

    tpr_score = float(cm_test[1][1])/(cm_test[1][1] + cm_test[1][0])
    fpr_score = float(cm_test[0][1])/(cm_test[0][0]+ cm_test[0][1])

    ax2 = fig.add_subplot(122)
    curve1 = ax2.plot(fpr_test, tpr_test)
    curve2 = ax2.plot([0, 1], [0, 1], color='navy', linestyle='--')
    dot = ax2.plot(fpr_score, tpr_score, marker='o', color='black')
    ax2.text(fpr_score, tpr_score, s = '(%.3f,%.3f)' %(fpr_score, tpr_score))
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.0])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('ROC curve (Test), AUC = %.4f'%auc_test)
    plt.savefig('ROC', dpi = 500)
    plt.show()

    return best_threshold

Зразок табличного графіку, створений цим кодом


Як розрахувати y_train_true, y_train_prob, y_test_true, y_test_prob?
Md. Rezwanul Haque

y_train_true, y_test_trueповинні бути легко доступні у маркованому наборі даних. y_train_prob, y_test_probє результатами з вашої навченої нейронної мережі.
Brian Chan

0

Коли вам також потрібні ймовірності ... Далі отримується значення AUC і все це складається в один постріл.

from sklearn.metrics import plot_roc_curve

plot_roc_curve(m,xs,y)

Коли у вас є ймовірності ... ви не можете отримати значення аукціону та графіки одним пострілом. Виконайте наступне:

from sklearn.metrics import roc_curve

fpr,tpr,_ = roc_curve(y,y_probas)
plt.plot(fpr,tpr, label='AUC = ' + str(round(roc_auc_score(y,m.oob_decision_function_[:,1]), 2)))
plt.legend(loc='lower right')

-1

Існує бібліотека під назвою metriculous, яка зробить це за вас:

$ pip install metriculous

Давайте спочатку знущаємось над деякими даними, які зазвичай надходять із тестового набору даних та моделей:

import numpy as np

def normalize(array2d: np.ndarray) -> np.ndarray:
    return array2d / array2d.sum(axis=1, keepdims=True)

class_names = ["Cat", "Dog", "Pig"]
num_classes = len(class_names)
num_samples = 500

# Mock ground truth
ground_truth = np.random.choice(range(num_classes), size=num_samples, p=[0.5, 0.4, 0.1])

# Mock model predictions
perfect_model = np.eye(num_classes)[ground_truth]
noisy_model = normalize(
    perfect_model + 2 * np.random.random((num_samples, num_classes))
)
random_model = normalize(np.random.random((num_samples, num_classes)))

Тепер ми можемо використовувати metriculous для створення таблиці з різними метриками та діаграмами, включаючи криві ROC:

import metriculous

metriculous.compare_classifiers(
    ground_truth=ground_truth,
    model_predictions=[perfect_model, noisy_model, random_model],
    model_names=["Perfect Model", "Noisy Model", "Random Model"],
    class_names=class_names,
    one_vs_all_figures=True, # This line is important to include ROC curves in the output
).save_html("model_comparison.html").display()

Криві ROC на виході: метрикулярні криві ROC

Ділянки можна масштабувати та перетягувати, і ви отримуєте додаткові відомості, коли наводите курсор миші на ділянку:

метрикулярна крива ROC

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.