Как построить кривую ROC на Python

88

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

user3847447
источник

Ответы:

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)) 
Uniquegino
источник
Значит, «preds» - это в основном ваши оценки pred_proba, а «model» - это ваш классификатор?
Крис Нильсен
@ChrisNielsen предвидит вас; да, модель - это обученный классификатор
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.

Кривые ROC

Отказ от ответственности: обратите внимание, что здесь используется созданная мной библиотека scikit-plot .

Рейи Накано
источник
3
Как рассчитать y_true ,y_probas ?
Md. Rezwanul Haque
3
Рейи Накано - Вы гений в обличье ангела. Вы сделали мой день. Этот пакет очень простой, но очень эффективный. Вам мое полное уважение. Небольшое примечание о приведенном выше фрагменте кода; линия позапрошлого shouln't это следующим образом: skplt.metrics.plot_roc_curve(y_true, y_probas)? Большое спасибо.
salvu
1
Этот ответ должен был быть выбран как правильный! Очень полезный пакет
Шриватса
24
У меня проблемы с использованием пакета. Каждый раз, когда я пытаюсь скормить графику ROC, он говорит мне, что у меня «слишком много индексов». Я кормлю свой 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.
Aerin
12
fpr, tpr, threshold = metrics.roc_curve (y_test, preds)
Aerin
что здесь означает «метрики»? что именно?
dekio
1
@dekio 'metrics' здесь от sklearn: от sklearn import metrics
Батист Путье,
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 - это прогнозируемые результаты вашей модели
Черри Ву
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?
Саид
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, это не работает (как метки), вы знаете, как это решить? а также кажется невозможным редактировать график (например, легенду)
Реут
4

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

Взгляните на файл readme на github, чтобы узнать больше! :)

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

Пример графа roc, созданного этим кодом

Брайан Чан
источник
Как рассчитать 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являются выходными данными вашей обученной нейронной сети.
Брайан Чан
0

Когда вам также нужны вероятности ... Следующее получает значение AUC и отображает все это за один раз.

from sklearn.metrics import plot_roc_curve

plot_roc_curve(m,xs,y)

Когда у вас есть вероятности ... вы не можете получить значение auc и графики за один раз. Сделайте следующее:

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')
агент18
источник
-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

efjnvdslndf
источник