分類問題中已有準確率、精準率和召回率,爲什麼還要提出ROC?

在上一篇“分類問題中的幾個衡量指標”中,我們介紹了分類問題中常見的幾種分類精度衡量指標。這些指標從整體到個體等不同程度上地體現了分類模型的分類精度。那麼,分類問題中已有準確率、精準率和召回率等指標,爲什麼還要提出ROC呢?什麼是ROC呢?

1、ROC提出的意義

對於理想的分類問題而言,其數據樣本中各個類別的數量是幾乎相等的。在這種理想狀態下,分類模型的準確率、精準率等指標是具有一定魯棒性的。但是在實際生活中,分類問題中的不同類別的樣本數量往往是不相等,是不平衡的。例如,根據病例數據判別當前病人是否患有癌症。在這個問題中,我們可以採集到的正常樣本的數量往往是異常樣本的幾倍甚至幾十倍。在這種情況下使用準確率、精準率等指標進行精度評價,我們可以發現這些指標會隨着兩種樣本數量的比例變化而發生變化。

針對上述問題,我們就需要一個具有魯棒性的指標來評估模型的精度,即不管在數據是否平衡的情況下,評估的指標都不會發生較大的變化甚至不變化。此時,ROC應運而生。

2、ROC的定義

ROC是Receiver Operating Characteristic的縮寫,是一種以假陽率(FPR)爲橫座標,以真陽率(TPR)爲縱座標,由FPR和TPR點對構成的一種曲線。該曲線的起點和終點分別爲(0,0)和(1,1)。當ROC曲線與座標軸構成的面積(S<1)越大時,則認爲該模型的分類性能越好。於是,AUC的概念也隨之出現。AUC是Area Under roc Curve的縮寫,它表示ROC曲線下方與座標軸之間的面積。因此,當AUC的數值(0<AUC<1)越大時,模型的分析性能越好。通常情況下,AUC一般爲0.5至1之間。

3、實例驗證

爲了驗證分類問題中ROC的魯棒性,本文以癌症數據爲例,進行實例驗證。在本次驗證過程中,我們選取了不同比例的正負樣本數據來探究不同數據平衡下的指標變化。

在本次實驗中,我們選取了邏輯迴歸模型作爲實驗的分類模型。首先,我們對數據樣本不平衡情況下的分類精度進行了分析;然後對數據樣本進行樣本平衡處理,再次進行分類精度評估。兩次實驗結果總結分析如圖1所示。

                                                圖1 實驗結果總結分析

從圖1我們可以發現,在數據樣本有不平衡變爲平衡的過程中,準確率、精準率、召回率均發生了一定的變化,而AUC值是基本沒有發生變化的。

爲更爲直觀的觀察AUC的魯棒性,我們將兩次實驗的ROC曲線進行了繪製,繪製結果如圖2所示。

 

                                                     圖2 ROC曲線

從圖2中,我們很直觀地發現兩次實驗的ROC曲線幾乎一模一樣。這在一定程度上證實了ROC曲線的魯棒性。當然,有興趣的童鞋還可以嘗試其他分類模型對ROC指標的魯棒性進行測試。本次實驗的代碼如下所示。

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_curve, auc
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt


def count(datas):
    a, b = 0, 0
    for element in datas:
        if element == 0:
            a += 1
        else:
            b += 1
    return a, b


data = load_breast_cancer()
x = data['data']
y = data['target']
data_names = data['feature_names']

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)
test_0, test_1 = count(y_test)
print("測試集中正樣本數量爲:%d,負樣本數量爲:%d, 正負比爲:%f" % (test_0, test_1, test_0/test_1))

model = LogisticRegression()
model.fit(x_train, y_train)
y_pre = model.predict(x_test)

Ac = accuracy_score(y_test, y_pre)
P = precision_score(y_test, y_pre)
R = recall_score(y_test, y_pre)
F_score = (2*P*R)/(P+R)
fpr, tpr, _ = roc_curve(y_test, model.predict_proba(x_test)[:, 1])
roc_auc = auc(fpr, tpr)
print("樣本比例更新前:")
print("Accuracy:%f\n Precision:%f\n Recall:%f\n F_score:%f" % (Ac, P, R, F_score))
print("AUC:%f" % roc_auc)

test_new = np.hstack((x_test, y_test.reshape(-1, 1)))
np.random.shuffle(test_new)
if test_0 > test_1:
    flag = 1
else:
    flag = 0
indexs = np.where(test_new[:, -1] == 1-flag)[0]
delete_indexs = np.random.choice(indexs, abs(test_0 - test_1))
test_new = np.delete(test_new, delete_indexs, 0)
x_test_new = test_new[:, :-1]
y_test_new = test_new[:, -1]

y_pre_new = model.predict(x_test_new)

Ac_new = accuracy_score(y_test_new, y_pre_new)
P_new = precision_score(y_test_new, y_pre_new)
R_new = recall_score(y_test_new, y_pre_new)
F_score_new = (2*P*R)/(P+R)

fpr_new, tpr_new, _ = roc_curve(y_test_new, model.predict_proba(x_test_new)[:, 1])
roc_auc_new = auc(fpr_new, tpr_new)
print("樣本比例更新後:")
print("Accuracy:%f\n Precision:%f\n Recall:%f\n F_score:%f" % (Ac_new, P_new, R_new, F_score_new))
print("AUC:%f" % roc_auc_new)

plt.figure(figsize=(5, 8))
ax1 = plt.subplot(211)
ax1.plot(fpr, tpr)
ax1.set_title("ROC(Receiver Operating Characteristic)-1")
ax1.plot([0, 1], [0, 1], '--', color='k')
ax1.set_xlabel('False Positive Rate')
ax1.set_ylabel('True Positive Rate')
# plt.fill_between(fpr, tpr, color='grey')
plt.show()

ax2 = plt.subplot(212)
ax2.plot(fpr_new, tpr_new)
ax2.set_title("ROC(Receiver Operating Characteristic)-2")
ax2.plot([0, 1], [0, 1], '--', color='k')
ax2.set_xlabel('False Positive Rate')
ax2.set_ylabel('True Positive Rate')
# plt.fill_between(fpr, tpr, color='grey')
plt.tight_layout()
plt.show()

歡迎各位童鞋進行點贊、轉載、評論!

               

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