使用scikit-learn計算分類器的ROC曲線及AUC值

在前面的博客中介紹了使用scikit-learn繪製分類器的學習曲線,今天介紹一下使用scikit-learn繪製分類器的ROC曲線,以及計算AUC的值。

ROC曲線主要用於衡量二分類器的性能,當正負樣本不均衡時,準確率和召回率不能合理度量分類器的性能。關於ROC曲線和AUC的計算scikit-learn工具包中主要提供了以下幾個函數:

1、roc_curve函數(只能用於二分類):根據模型預測結果(概率,置信度等)和樣本真實標籤,按照模型預測結果降序排序依次選擇閾值,基於閾值計算fpr、tpr,基於fpr和tpr即可得到分類器的ROC曲線

2、auc函數:基於roc_curve函數返回fpr、tpr序列計算二分類器的AUC值

3、roc_auc_score函數:基於樣本真實標籤y_target和模型預測結果(概率,置信度等)計算AUC的值,可以用於計算多分類器的AUC數值

下面通過例子看一下函數的具體使用方法:

roc_curve示例:

根據模型預測結果(概率,置信度等)和樣本真實標籤,按照模型預測結果降序排序依次選擇閾值,基於閾值計算fpr/tpr。

from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.metrics import auc
import numpy as np


y = np.array([1, 1, 2, 2])
scores = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = roc_curve(y, scores, pos_label=2)

fpr, tpr, thresholds

輸出的fpr、tpr和thresholds如下:

(array([0. , 0. , 0.5, 0.5, 1. ]),
array([0. , 0.5, 0.5, 1. , 1. ]),
array([1.8 , 0.8 , 0.4 , 0.35, 0.1 ]))

基於fpr(x軸)和tpr(y軸)繪製ROC曲線如下:

%matplotlib inline
from matplotlib import pyplot as plt

plt.plot(fpr, tpr)
plt.xlabel("FPR")
plt.ylabel("TPR")
plt.xlim([0, 1])
plt.ylim([0, 1])

auc示例:

基於roc_curve函數返回fpr、tpr序列計算AUC的值(和roc_auc_score等價)。

import numpy as np
y = np.array([1, 1, 2, 2])
pred = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = roc_curve(y, pred, pos_label=2)
auc(fpr, tpr), roc_auc_score(y, pred)

輸出結果如下:

(0.75, 0.75)

roc_auc_score示例:

基於樣本真實標籤y_target和模型預測結果(概率,置信度等)計算AUC的值,可以用於計算多分類器的AUC數值。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
from sklearn.metrics import roc_curve, roc_auc_score, auc, plot_roc_curve
from sklearn.multiclass import OneVsOneClassifier, OneVsRestClassifier
from sklearn.preprocessing import label_binarize
from sklearn import datasets
from sklearn.model_selection import train_test_split
np.random.seed(100)

# 加載iris數據集
iris = datasets.load_iris()
X = iris.data
y = iris.target
print(X.shape, y.shape)
n_samples, n_features = X.shape

# iris數據集加入噪聲,使得ROC不是那麼完美
X = np.c_[X, np.random.randn(n_samples, 50 * n_features)]
# y = label_binarize(y, classes=[0, 1, 2])
# n_classes = y.shape[1]
# 訓練樣本的類別數量
n_classes = 3

# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5, random_state=0)
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)

# 使用One-vs-One模式訓練SVM分類器
clf = OneVsRestClassifier(SVC(kernel="linear", probability=True))
clf.fit(X_train, y_train)

# 計算分類器在測試集上的決策值
y_scores = clf.predict_proba(X_test)
print(y_scores.shape)

# 繪製每個類別的ROC曲線
fig, axes = plt.subplots(2, 2, figsize=(8, 8))
colors = ["r", "g", "b", "k"]
markers = ["o", "^", "v", "+"]

y_test = label_binarize(y_test, classes=clf.classes_)
for i in range(n_classes):
    # 計算每個類別的FPR, TPR 
    fpr, tpr, thr = roc_curve(y_test[:, i], y_scores[:, i])
#     print("classes_{}, fpr: {}, tpr: {}, threshold: {}".format(i, fpr, tpr, thr))
    # 繪製ROC曲線,並計算AUC值
    axes[int(i / 2), i % 2].plot(fpr, tpr, color=colors[i], marker=markers[i], label="AUC: {:.2f}".format(auc(fpr, tpr)))
    axes[int(i / 2), i % 2].set_xlabel("FPR")
    axes[int(i / 2), i % 2].set_ylabel("TPR")
    axes[int(i / 2), i % 2].set_title("Class_{}".format(clf.classes_[i]))
    axes[int(i / 2), i % 2].legend(loc="lower right")

print("AUC:", roc_auc_score(y_test, clf.predict_proba(X_test), multi_class="ovr", average=None))

輸出結果如下:

AUC: [0.99647266 0.8237037  0.90196078]

這個例子中是一個多分類問題,y_scores和y_test的形狀都是(n_samples, 3),且y_scores、y_test的每列分別代表clf.classes_每種類型的真實標籤和預測概率,然後基於每種類型的真是標籤和預測概率計使用roc_curve函數計算fpr和tpr,並使用auc函數計算AUC的值。最後使用roc_auc_score函數計算多分類的整體AUC值。

在計算多分類的roc_auc_score值時,可以通過參數multi_class : {'raise', 'ovr', 'ovo'}控制多分類模型是使用哪種模式訓練的,參數average : {'micro', 'macro', 'samples', 'weighted'} or None表示使用何種方式計算多分類器AUC的值,常用的包括宏平均和微平均。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章