it-source

파이썬에서 ROC 곡선을 그리는 방법

criticalcode 2023. 9. 3. 16:21
반응형

파이썬에서 ROC 곡선을 그리는 방법

로지스틱 회귀 패키지를 사용하여 Python에서 개발한 예측 모델의 정확성을 평가하기 위해 ROC 곡선을 작성하려고 합니다.실제 양성률과 거짓 양성률을 계산했지만, 다음을 사용하여 정확하게 플롯하는 방법을 찾을 수 없습니다.matplotlibAUC 값을 계산합니다.내가 어떻게 그럴 수 있을까?

다음과 같은 두 가지 방법을 시도할 수 있습니다.model질문 학습 예측 변수입니다.

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

이것은 일련의 실측값 레이블과 예측 확률을 고려할 때 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 Curves

고지 사항:이것은 제가 만든 스크킷 플롯 라이브러리를 사용합니다.

matplotlib을 사용한 이항 분류에 대한 AUC 곡선

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 Curve

여기서 문제가 무엇인지 전혀 명확하지 않지만 배열이 있는 경우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)

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

스택 오버플로, 스크킷 학습 문서 등의 여러 주석을 기반으로 정말 간단한 방법으로 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()

결과:

패키지의 Github 및 설명서에서 더 많은 예제를 찾을 수 있습니다.

앞의 답변에서는 실제로 TP/센서를 계산했다고 가정합니다.수동으로 이 작업을 수행하는 것은 좋지 않습니다. 계산 과정에서 실수하기 쉬우므로 라이브러리 기능을 사용하는 것이 좋습니다.

scikit_dll의 plot_roc 함수는 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])

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

이제 미터법을 사용하여 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 곡선은 출력에서 다음과 같습니다.

플롯은 확대/축소 및 드래그가 가능하며, 플롯 위에 마우스를 올려 놓으면 다음과 같은 세부 정보를 볼 수 있습니다.

metriculous ROC curve

공식 문서 양식 스크킷을 따를 수도 있습니다.

https://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html#sphx-glr-auto-examples-model-selection-plot-roc-py

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

이 코드로 생성된 샘플 로코그래프

확률이 필요할 때도...다음은 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')

제 코드에서는 X_train과 y_train이 있고 클래스는 0과 1입니다.clf.predict_proba()방법은 모든 데이터 점에 대한 두 클래스의 확률을 계산합니다.저는 임계값이 다른 클래스 1의 확률을 비교합니다.

probability = clf.predict_proba(X_train) 

def plot_roc(y_train, probability):
  threshold_values = np.linspace(0,1,100)       #Threshold values range from 0 to 1
  FPR_list = []
  TPR_list = []

  for threshold in threshold_values:            #For every value of threshold
    y_pred = []                                 #Classify every data point in the test set

#prob is an array consisting of 2 values - Probability of datapoint in Class0 and Class1.
    for prob in probability:
      if ((prob[1])<threshold):                 #Prob of class1 (positive class) 
        y_pred.append(0)                                                  
        continue
      elif ((prob[1])>=threshold): y_pred.append(1)

#Plot Confusion Matrix and Obtain values of TP, FP, TN, FN
    c_m = confusion_matrix(y, y_pred)           
    TN = c_m[0][0]                                                          
    FP = c_m[0][1]
    FN = c_m[1][0]      
    TP = c_m[1][1]                                                      

    FPR = FP/(FP + TN)                          #Obtain False Positive Rate                                          
    TPR = TP/(TP + FN)                          #Obtain True Positive Rate                                      

    FPR_list.append(FPR)
    TPR_list.append(TPR)

  fig = plt.figure()
  plt.plot(FPR_list, TPR_list)                                    
  plt.ylabel('TPR')
  plt.xlabel('FPR')
  plt.show()

제가 관리하는 새로운 오픈 소스는 모델 성능을 테스트할 수 있는 여러 가지 방법이 있습니다.ROC 곡선을 보려면 다음을 수행할 수 있습니다.

from deepchecks.checks import RocReport
from deepchecks import Dataset

RocReport().run(Dataset(df, label='target'), model)

결과는 다음과 같습니다. RocReport의 더 정교한 예는 여기에서 찾을 수 있습니다.

ROC 곡선은 이진 분류에만 사용되므로 데이터 이진화 및 레이블링을 사용합니다.

# Binarize data for getting AUC 
y_test_bin = label_binarize(y_test, classes=range(y_train.min() , y_train.max())) 
y_pred_bin = label_binarize(Predicted_result, classes=range(y_train.min() , y_train.max()))

# Calculate FP , TP rate
fpr, tpr, _ = roc_curve(y_test_bin.ravel(), y_pred_bin.ravel()  )

# Get AUC , 
auc = roc_auc_score(y_test_bin, y_pred_bin, average='micro', multi_class='ovr')
 
#create ROC curve
plt.plot(fpr,tpr , label= f"AUC = {auc}" , )
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0]) 
plt.title('ROC')
plt.legend(loc=7)
plt.figure(figsize = [])

plt.show()

여기 w3Schools에 기록된 바와 같이:

import matplotlib.pyplot as plt

def plot_roc_curve(true_y, y_prob):
    """
    plots the roc curve based of the probabilities
    """

    fpr, tpr, thresholds = roc_curve(true_y, y_prob)
    plt.plot(fpr, tpr)
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')

plot_roc_curve(y, y_proba)
print(f'model AUC score: {roc_auc_score(y, y_proba)}')

언급URL : https://stackoverflow.com/questions/25009284/how-to-plot-roc-curve-in-python

반응형