分类问题中已有准确率、精准率和召回率,为什么还要提出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()

欢迎各位童鞋进行点赞、转载、评论!

               

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