分類問題(四)ROC曲線


ROC曲線

ROC曲線是二元分類器中常用的工具,它的全稱是 Receiver Operating Characteristic,接收者操作特征曲線。它與precision/recall 曲線特別相似,但是它畫出的是true positive rate(recall的另一種叫法)對應false positive rate (FPR)的圖。FPR是“負實例”(negative instances) 被錯誤地分類成“正實例”(positive)的比率。它等同於 1 減去true negative rate(TNR,“負實例”被正確地分類成“負實例”的比率)。TNR也被稱為特異性(specificity)。所以ROC曲線畫出的也是 sensitivity(也就是recall)vs (1 – specificity)。

為了畫出ROC 曲線,我們首先需要計算在不同閾值下的TPR與FPR值,使用roc_curve() 方法:

from sklearn.metrics import roc_curve

fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)

 

然后使用matplotlib 畫出FPR對應TPR的圖:

def plot_roc_curve(fpr, tpr, label=None):
    plt.plot(fpr, tpr, linewidth=2, label=label)
    plt.plot([0, 1], [0, 1], 'k--') #加上虛線對角線

plot_roc_curve(fpr, tpr)
plt.show()

 

同樣,這里也有一個折中,更高的recall(TPR)也就意味着分類器會產生更多的false positives(FPR)。虛線代表的是一個完全隨機的分類器的ROC曲線,一個好的分類器的ROC曲線要盡可能地遠離這條虛線,並要盡可能地接近左上角。

一種比較分類器的辦法是評估AUC(area under the curve,曲線下方面積),一個完美的分類器的ROC AUC應等於1,而一個完全隨機的分類器的ROC AUC則為0.5。sk-learn提供了一個方法用於計算ROC AUC:

from sklearn.metrics import roc_auc_score

roc_auc_score(y_train_5, y_scores)
>0.9604938554008616

 

由於ROC曲線與precision/recall(或者PR)曲線非常相似,所以大家可能會好奇到底使用哪個。根據經驗,任何時候當positive 類別很少、或是在關注false positive甚於false negative時,使用PR曲線。反之則使用ROC曲線。例如,我們看一下上一個ROC曲線(以及ROC AUC分數),我們可能認為分類器非常好。但是這主要是因為數據集中positive instances(也就是數字5)較少,相對於“非5”少很多。相反,從PR曲線來看,我們可以看到其實這個分類器還有提升的空間(PR曲線應該盡可能地靠近右上角)。

我們接下來訓練一個RandomForestClassifier,並對比它的ROC 曲線以及ROC AUC分數。首先,我們需要得到訓練集中每條數據的分數。但是RandomForestClassifier類並沒有提供decision_function() 的方法,它提供的是一個predict_proba() 方法。一般sk-learn中的分類器中,基本都是提供的這兩個方法中的其一。predict_proba() 方法返回一個數組,里面每行是一條數據,每列是一個類別,里面的數值就是這條數據屬於這個類別的概率(例如,某條數據有70%的概率代表數字5)。

from sklearn.ensemble import RandomForestClassifier

forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3, method='predict_proba')
y_probas_forest
>array([[0.1, 0.9],

       [1. , 0. ],

       [0.9, 0.1],

       ...,

       [0. , 1. ],

       [1. , 0. ],

       [1. , 0. ]])

 

但是為了畫出ROC曲線,我們需要的是分數(scores),並不是概率。一個簡單的辦法是使用positive類的概率作為分數:

y_scores_forest = y_probas_forest[:, 1]
fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5, y_scores_forest)

 

現在我們已經有了分數,可以畫出ROC曲線(最好是也畫出第一個分類器的ROC曲線作為對比):

plt.plot(fpr, tpr, 'b:', label='SGD')
plot_roc_curve(fpr_forest, tpr_forest, 'Random Forest')
plt.legend(loc='lower right')
plt.show()

 

如上圖所示,RandomForestClassifier的ROC曲線看起來比SGDClassifier的更好:它更接近於左上角。顯而易見,它的ROC AUC分數也會更高:

roc_auc_score(y_train_5, y_scores_forest)
>0.9920527492698306

 

如果進一步計算它的precision與recall的話,可以分別得到98% 的precision,以及82%的recall:

y_train_forest_pred = cross_val_predict(forest_clf, X_train, y_train_5, cv=3)
precision_score(y_train_5, y_train_forest_pred)
>0.986046511627907

recall_score(y_train_5, y_train_forest_pred)
>0.8212506917542889

 

相較上一個分類器,有了很大的提升。

至此,希望大家已經了解了:

  • 如何訓練一個二元分類器
  • 為任務選擇合適的指標
  • 使用交叉驗證評估分類器
  • 使用precision/recall tradeoff 滿足你的需求
  • 通過ROC曲線以及ROC AUC分數比較不同的模型

在二元分類器完成之后,我們之后接下來繼續看一下多類別分類,讓分類器不僅僅是只區分數字5。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM