So zeichnen Sie die ROC-Kurve in Python

86

Ich versuche, eine ROC-Kurve zu zeichnen, um die Genauigkeit eines Vorhersagemodells zu bewerten, das ich in Python mithilfe logistischer Regressionspakete entwickelt habe. Ich habe sowohl die wahre positive Rate als auch die falsche positive Rate berechnet. Ich kann jedoch nicht herausfinden, wie diese mit matplotlibdem AUC-Wert korrekt dargestellt und berechnet werden können. Wie könnte ich das machen?

user3847447
quelle

Antworten:

109

Hier sind zwei Möglichkeiten, die Sie ausprobieren können, vorausgesetzt, Sie modelsind ein sklearn-Prädiktor:

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')

oder Versuche

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)) 
Uniquegino
quelle
Also ist 'preds' im Grunde Ihre prädict_proba-Scores und 'model' ist Ihr Klassifikator?
Chris Nielsen
@ ChrisNielsen preds is y hat; Ja, Modell ist der trainierte Klassifikator
Uniquegino
Was ist all thresholds, wie werden sie berechnet?
Mrgloom
@mrgloom sie werden automatisch von sklearn.metrics.roc_curve
erobertc
88

Dies ist der einfachste Weg, eine ROC-Kurve zu zeichnen, wenn eine Reihe von Grundwahrheitsbezeichnungen und vorhergesagten Wahrscheinlichkeiten gegeben sind. Das Beste daran ist, dass die ROC-Kurve für ALLE Klassen dargestellt wird, sodass Sie auch mehrere gut aussehende Kurven erhalten

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()

Hier ist eine Beispielkurve, die von plot_roc_curve generiert wurde. Ich habe den Beispiel-Ziffern-Datensatz von scikit-learn verwendet, sodass es 10 Klassen gibt. Beachten Sie, dass für jede Klasse eine ROC-Kurve aufgezeichnet wird.

ROC-Kurven

Haftungsausschluss: Beachten Sie, dass hierfür die von mir erstellte Scikit-Plot- Bibliothek verwendet wird.

Reii Nakano
quelle
3
Wie berechnet man y_true ,y_probas ?
Md. Rezwanul Haque
3
Reii Nakano - Du bist ein Genie in der Verkleidung eines Engels. Du hast meinen Tag gemacht. Dieses Paket ist soooo einfach und doch so effektiv. Du hast meinen vollen Respekt. Nur eine kleine Anmerkung zu Ihrem Code-Snippet oben; Die vorletzte Zeile sollte nicht lauten : skplt.metrics.plot_roc_curve(y_true, y_probas)? Ein großes Dankeschön.
Salvu
1
Dies sollte als die richtige Antwort ausgewählt worden sein! Sehr nützliches Paket
Srivathsa
23
Ich habe Probleme beim Versuch, das Paket zu verwenden. Jedes Mal, wenn ich versuche, die Plot-Roc-Kurve zu füttern, wird mir mitgeteilt, dass ich "zu viele Indizes" habe. Ich füttere den my y_test und pred dazu. Ich kann meine Vorhersagen treffen. Aber ich kann die Handlung wegen dieses Fehlers nicht bekommen. Liegt es an der Version von Python, die ich verwende?
Herc01
4
Ich musste meine y_pred-Daten so umformen, dass sie die Größe Nx1 hatten, anstatt nur eine Liste: y_pred.reshape (len (y_pred), 1). Jetzt erhalte ich stattdessen den Fehler 'IndexError: Index 1 ist für Achse 1 mit Größe 1 außerhalb der Grenzen', aber es wird eine Zahl gezeichnet, was vermutlich darauf zurückzuführen ist, dass der Code erwartet, dass ein binärer Klassifizierer mit jeder Klassenwahrscheinlichkeit einen Nx2-Vektor bereitstellt
Vidar
41

Es ist überhaupt nicht klar, wo das Problem liegt, aber wenn Sie ein Array true_positive_rateund ein Array haben false_positive_rate, ist das Zeichnen der ROC-Kurve und das Abrufen der AUC so einfach wie:

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)
ebarr
quelle
7
Diese Antwort wäre viel besser gewesen, wenn der Code FPR- und TPR-Oneliner enthalten hätte.
Aerin
12
fpr, tpr, Schwelle = Metriken.roc_curve (y_test, preds)
Aerin
Was bedeutet "Metrik" hier? was ist das genau
Dekio
1
@dekio 'Metriken' hier ist von sklearn: von sklearn Importmetriken
Baptiste Pouthier
38

AUC-Kurve Für die binäre Klassifizierung mit 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

Laden Sie den Brustkrebs-Datensatz

breast_cancer = load_breast_cancer()

X = breast_cancer.data
y = breast_cancer.target

Teilen Sie den Datensatz

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

Modell

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

Richtigkeit

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

AUC-Kurve

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-Kurve

Ajayramesh
quelle
19

Hier ist Python-Code zur Berechnung der ROC-Kurve (als Streudiagramm):

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()
Mona
quelle
Sie haben den gleichen Index der äußeren Schleife "i" auch in der inneren Schleife verwendet.
Ali Yeşilkanat
Referenz ist 404.
Luckydonald
@Mona, danke, dass du darauf hingewiesen hast, wie ein Algorithmus funktioniert.
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)
Kirsche Wu
quelle
2
Wie berechnet man y_true = # true labels, y_probas = # predicted results?
Md. Rezwanul Haque
2
Wenn Sie die Grundwahrheit haben, ist y_true Ihre Grundwahrheit (Bezeichnung), y_probas ist das vorhergesagte Ergebnis Ihres Modells
Cherry Wu
6

Bei den vorherigen Antworten wird davon ausgegangen, dass Sie TP / Sens tatsächlich selbst berechnet haben. Es ist eine schlechte Idee, dies manuell zu tun. Es ist leicht, Fehler bei den Berechnungen zu machen. Verwenden Sie stattdessen eine Bibliotheksfunktion für all dies.

Die Funktion plot_roc in scikit_lean macht genau das, was Sie brauchen: http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html

Der wesentliche Teil des Codes ist:

  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])
Max
quelle
Wie berechnet man y_score?
Saeed
6

Basierend auf mehreren Kommentaren aus dem Stackoverflow, der Scikit-Learn-Dokumentation und einigen anderen habe ich ein Python-Paket erstellt, um die ROC-Kurve (und andere Metriken) auf wirklich einfache Weise zu zeichnen.

So installieren Sie das Paket: pip install plot-metric(Weitere Informationen am Ende des Beitrags)

So zeichnen Sie eine ROC-Kurve (Beispiel aus der Dokumentation):

Binäre Klassifizierung

Laden wir einen einfachen Datensatz und erstellen einen Zug- und Testsatz:

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)

Trainieren Sie einen Klassifikator und sagen Sie den Testsatz voraus:

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]

Sie können jetzt plot_metric verwenden, um die ROC-Kurve zu zeichnen:

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()

Ergebnis: ROC-Kurve

Weitere Beispiele finden Sie auf dem Github und in der Dokumentation des Pakets:

Yohann L.
quelle
Ich habe es versucht und es ist schön, aber es scheint nicht nur zu funktionieren, wenn Klassifizierungsbezeichnungen 0 oder 1 waren, aber wenn ich 1 und 2 habe, funktioniert es nicht (als Bezeichnungen). Wissen Sie, wie man das löst? und es scheint auch unmöglich, das Diagramm zu bearbeiten (wie die Legende)
Reut
4

Ich habe eine einfache Funktion erstellt, die in einem Paket für die ROC-Kurve enthalten ist. Ich habe gerade angefangen, maschinelles Lernen zu üben. Bitte lassen Sie mich auch wissen, wenn dieser Code ein Problem hat!

Weitere Informationen finden Sie in der Github-Readme-Datei! :) :)

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

Ein Beispiel-ROC-Diagramm, das mit diesem Code erstellt wurde

Brian Chan
quelle
Wie berechnet man y_train_true, y_train_prob, y_test_true, y_test_prob?
Md. Rezwanul Haque
y_train_true, y_test_truesollte in einem beschrifteten Datensatz leicht verfügbar sein. y_train_prob, y_test_probsind Ausgänge Ihres trainierten neuronalen Netzwerks.
Brian Chan
-1

Es gibt eine Bibliothek namens metriculous , die das für Sie erledigt :

$ pip install metriculous

Lassen Sie uns zunächst einige Daten verspotten, die normalerweise aus dem Testdatensatz und den Modellen stammen:

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)))

Jetzt können wir mithilfe von Metrik eine Tabelle mit verschiedenen Metriken und Diagrammen erstellen, einschließlich ROC-Kurven:

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()

Die ROC-Kurven in der Ausgabe: metrische ROC-Kurven

Die Diagramme sind zoombar und ziehbar, und Sie erhalten weitere Details, wenn Sie mit der Maus über das Diagramm fahren:

metrische ROC-Kurve

efjnvdslndf
quelle