4.3 ROC 曲线(Receiver Operating Characteristic curve)
ROC曲线为接受者操作特性曲线是指在特定刺激条件下,以被试在不同判断标准下所得的假阳率为横坐标,真阳率为纵坐标,画得的各点的连线。
AUC(Area Underthe Curve)为ROC下面的面积。
4.4 P-R(Recall-Precision)曲线
横坐标为,纵坐标为召回率,纵坐标为精确度。
如何选择ROC和P-R曲线
- 在很多实际问题中,正负样本数量往往很不均衡。比如,计算广告领域经常涉及转化率模型,正样本的数量往往是负样本数量的1/1000,甚至1/10000。若选择不同的测试集,P-R曲线的变化就会非常大,而ROC曲线则能够更加稳定地反映模型本身的好坏。所以,ROC曲线的适用场景更多,被广泛用于排序、推荐、广告等领域。
- 但需要注意的是,选择P-R曲线还是ROC曲线是因实际问题而异的,如果研究者希望更多地看到模型在特定数据集上的表现,P-R曲线则能够更直观地反映其性能。
- PR曲线比ROC曲线更加关注正样本,而ROC则兼顾了两者。
- AUC越大,反映出正样本的预测结果更加靠前(推荐的样本更能符合用户的喜好)。
- 当正负样本比例失调时,比如正样本1个,负样本100个,则ROC曲线变化不大,此时用PR曲线更加能反映出分类器性能的好坏。这个时候指的是两个分类器,因为只有一个正样本,所以在画auc的时候变化可能不太大;但是在画PR曲线的时候,因为要召回这一个正样本,看哪个分类器同时召回了更少的负样本,差的分类器就会召回更多的负样本,这样precision必然大幅下降,这样分类器性能对比就出来了。
4.5 Kappa系数
K=(P0-Pe)/(1-Pe)
P0是每一类正确分类的样本数量之和除以总样本数,也就是总体分类精度
假设每一类的真实样本个数分别为a1,a2,...,aC,而预测出来的每一类的样本个数分别为b1,b2,...,bC,总样本个数为n,则有Pe=( a1×b1+a2×b2+…+aC×bC)/(n×n)
4.6实际案例
让我们来看一个例子,比如有如下混淆矩阵:
判断 |
||||
A |
B |
C |
||
实际 |
A |
239 |
21 |
16 |
B |
16 |
73 |
4 |
|
C |
6 |
9 |
280 |
- 所有案例数:239+21+16+16+73+4+6+9+28=664;
- 判断为A的案例数:239+16+6=261;
- 判断为B的案例数:21+73+9=103;
- 判断为C的案例数:16+4+280=300;
- A的案例数:239+21+16=276;
- B的案例数:16+73+4=93;
- C的案例数:6+9+280=295。
这样:
- P0=(239+73+280)/664=0.8916;
- Pe=(261×276+103×93+300×295)/(64×64)=0.3883;
- K=(0.8916-0.3883)/(1-0.3883)=0.8228。
通过K的值,可以判定模型的好坏:
- 0.0~0.20:极低的一致性(slight);
- 0.21~0.40:一般的一致性(fair);
- 0.41~0.60:中等的一致性(moderate);
- 0.61~0.80:高度的一致性(substantial);
- 0.81~1:几乎完全一致(almostperfect)。
4.7程序的实现
前面讲课那么多指标,其实在Python里面可以利用sklearn这个插件快速的画出这些指标和算法。利用这个工具之前当然需要下载安装这个插件。
>pip3 install sklearn
下面来讲解一下这个代码。
# coding=UTF-8 from sklearn import metrics from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score from sklearn.metrics import precision_score from sklearn.metrics import recall_score from sklearn.metrics import f1_score import matplotlib.pylab as plt import numpy as np import matplotlib import matplotlib.pyplot as plt from sklearn.metrics import precision_recall_curve #真实值 GTlist = [1,1,0,1,1,0,1,0,0,1] #模型预测值 Problist = [1,0,1,1,1,1,1,1,0,1] y_true = np.array(GTlist) y_pred = np.array(Problist) #混淆矩阵 confusion_matrix = confusion_matrix(y_true, y_pred) print("混淆矩阵:") print(confusion_matrix) #准确性 accuracy = '{:.1%}'.format(accuracy_score(y_true, y_pred)) print("准确性:",end='') print(accuracy) #精确性 precision = '{:.1%}'.format(precision_score(y_true, y_pred)) print("精确性:",end='') print(precision) #召回率 recall = '{:.1%}'.format(recall_score(y_true, y_pred)) print("召回率:",end='') print(recall) #F1值 f1score = '{:.1%}'.format(f1_score(y_true, y_pred)) print("F1值:",end='') print(f1score) #初始化画图数据 #真实值 GTlist = [1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0,0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0] #模型预测值 Problist = [0.99, 0.98, 0.97, 0.93, 0.85, 0.80, 0.79, 0.75, 0.70, 0.65,0.64, 0.63, 0.55, 0.54, 0.51, 0.49, 0.30, 0.2, 0.1, 0.09] fpr, tpr, thresholds = metrics.roc_curve(GTlist, Problist, pos_label=1) roc_auc = metrics.auc(fpr, tpr) #auc为Roc曲线下的面积 print("AUC值:",end='') print('{:.1%}'.format(roc_auc)) #ROC曲线 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, 1.1]) plt.ylim([-0.1, 1.1]) plt.xlabel('False Positive Rate') #横坐标是fpr plt.ylabel('True Positive Rate') #纵坐标是tpr plt.title('Receiver operating characteristic example') plt.show() #P-R曲线 plt.figure("P-R Curve") plt.title('Precision/Recall Curve') plt.xlabel('Recall') plt.ylabel('Precision') #y_true为样本实际的类别,y_scores为样本为正例的概率 y_true = np.array(GTlist) y_scores = np.array(Problist) precision, recall, thresholds = precision_recall_curve(y_true, y_scores) plt.plot(recall,precision) plt.show()
真实值GTlist =[1,1,0,1,1,0,1,0,0,1]
模型预测值Problist= [1,0,1,1,1,1,1,1,0,1]
现在有10位病人来看病,其中3号、6号、8号和9号病人是没有疾病的(绿色),其他剩余6位有疾病(红色)。
编号 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
实际 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
1 |
检查 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
1号、4号、5号、7号和10号病人被查出来(真阳性,红色);2号病人没有被查出来(漏诊,橙色);3号、6号和8号被误诊(误诊,蓝色),另外9号(真隐性,绿色),通过运行这段代码,得到如下结果:
混淆矩阵:
[[1 3]
[1 5]]
准确性:60.0%
精确性:62.5%
召回率:83.3%
F1值:71.4%
我们来验证一下,真阳性:5、真阴性:1、假阳性:3、假阴性:1,所以混淆矩阵为:
预测 |
|||
假 |
真 |
||
实际 |
假 |
1 |
3 |
真 |
1 |
5 |
由此,可以看出算出来的矩阵与正式的矩阵的对应关系。假在前,真在后,一行代表实际中的实际中的一行。
准确性:(1+5)/10=60%
精确性:5/8=62.5%
召回率:5/6=83.3%
F1 Score=62.5%×83.3%×2/(62.5%+83.3%)=1.04125/1.458=71%
可见这些值都是正确的。接下来再看下面的数据。
#真实值
GTlist = [1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,1.0, 0.0, 1.0,0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
#模型预测值
Problist = [0.99, 0.98, 0.97, 0.93, 0.85,0.80, 0.79, 0.75, 0.70, 0.65,0.64, 0.63, 0.55, 0.54, 0.51, 0.49, 0.30, 0.2,0.1, 0.09]
GTlist表示真实样本,1.0代表真样本,0.0代表假样本;
Problist表示预测样本,每个值表示预测到对应真实样本为真的概率。比如第一个0.99表示预测第一个正样本的概率为99%,第三个0.97表示预测第三个假样本的概率为97%。通过运行我们得到如下曲线图。
我们考察A(0,0)、B(1,1)、C(0,1)、D(1,0)四个点:
- A(0,0):表示真阳率与假阳率均为0,表示什么都没有测试到;
- B(1,1):表示真阳率与假阳率均为100%;
- C(0,1):真阳率为100%,假阳率均为0,测试到的全是真的;
- D(1,0):真阳率为0,假阳率均为100%,测试到的全是假的。
由此可见C点的情况最高,所以曲线越靠近左上角说明算法最好。
另外,上面代码也会给出了化P-R图的方法,对于ROC曲线,采用同一个测试数据,画出来的图如下显示。
4.8 最终分析
from sklearn.neighbors import KNeighborsClassifier def my_score(): X,y =datasets.load_wine().data,datasets.load_wine().target X_train, X_test,y_train, y_test = train_test_split(X, y, random_state=68) knn =KNeighborsClassifier() knn.fit(X_train,y_train) print("训练集得分:\n{:.2%}".format(knn.score(X_train,y_train))) print("测试集得分:\n{:.2%}".format(knn.score(X_test,y_test))) y_true = y_test y_pred =knn.predict(X_test) #混淆矩阵 print("混淆矩阵:\n",confusion_matrix(y_true,y_pred)) #准确性 accuracy ='{:.1%}'.format(accuracy_score(y_true, y_pred)) print("准确性:",accuracy) #精确性 precision ='{:.1%}'.format(precision_score(y_true, y_pred, average='micro')) print("精确性:",precision) #召回率 recall ='{:.1%}'.format(recall_score(y_true, y_pred, average='micro')) print("召回率:",recall) #F1值 f1score ='{:.1%}'.format(f1_score(y_true, y_pred, average='micro')) print("F1值:",f1score) X,y =make_blobs(n_samples=200,centers=2, random_state=1,cluster_std=5) X_train, X_test,y_train, y_test = train_test_split(X, y, random_state=68) gnb = GaussianNB() gnb.fit(X_train,y_train) predict_proba =gnb.predict_proba(X_test) mylist = [None] *int(predict_proba.shape[0]) i = 0 for my_predict_proba inpredict_proba: sign = int(y[i]) mylist[i] =my_predict_proba[sign] i = i+1 GTlist = y_test Problist = mylist fpr, tpr, thresholds =roc_curve(GTlist, Problist, pos_label=1) roc_auc =metrics.auc(fpr, tpr) #auc为Roc曲线下的面积 print("AUC值:",end='') print('{:.1%}'.format(roc_auc)) plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False #ROC曲线 plt.plot(fpr, tpr,'b',label='AUC = %0.2f'% roc_auc) plt.legend(loc='lowerright') # plt.plot([0, 1], [0,1], 'r--') plt.xlim([-0.1, 1.1]) plt.ylim([-0.1, 1.1]) plt.xlabel(u'假阳性率') #横坐标是fpr plt.ylabel(u'真阳性率') #纵坐标是tpr plt.title(u'接收器工作特性示例') plt.show() #P-R曲线 plt.figure(u"P-R 曲线") plt.title(u'精度/召回曲线') plt.xlabel(u'召回') plt.ylabel(u'精度') #y_true为样本实际的类别,y_scores为样本为正例的概率 y_true =np.array(GTlist) y_scores =np.array(Problist) precision, recall,thresholds = precision_recall_curve(y_true, y_scores) plt.plot(recall,precision) plt.show()
输出
训练集得分: 76.69% 测试集得分: 80.00% 混淆矩阵: [[17 0 0] [ 2 12 3] [ 3 1 7]] 准确性: 80.0% 精确性: 80.0% 召回率: 80.0% F1值: 80.0% AUC值:57.8%
—————————————————————————————————
软件安全测试
https://study.163.com/course/courseMain.htm?courseId=1209779852&share=2&shareId=480000002205486
接口自动化测试
https://study.163.com/course/courseMain.htm?courseId=1209794815&share=2&shareId=480000002205486
DevOps 和Jenkins之DevOps
https://study.163.com/course/courseMain.htm?courseId=1209817844&share=2&shareId=480000002205486
DevOps与Jenkins 2.0之Jenkins
https://study.163.com/course/courseMain.htm?courseId=1209819843&share=2&shareId=480000002205486
Selenium自动化测试
https://study.163.com/course/courseMain.htm?courseId=1209835807&share=2&shareId=480000002205486
性能测试第1季:性能测试基础知识
https://study.163.com/course/courseMain.htm?courseId=1209852815&share=2&shareId=480000002205486
性能测试第2季:LoadRunner12使用
https://study.163.com/course/courseMain.htm?courseId=1209980013&share=2&shareId=480000002205486
性能测试第3季:JMeter工具使用
https://study.163.com/course/courseMain.htm?courseId=1209903814&share=2&shareId=480000002205486
性能测试第4季:监控与调优
https://study.163.com/course/courseMain.htm?courseId=1209959801&share=2&shareId=480000002205486
Django入门
https://study.163.com/course/courseMain.htm?courseId=1210020806&share=2&shareId=480000002205486
啄木鸟顾老师漫谈软件测试
https://study.163.com/course/courseMain.htm?courseId=1209958326&share=2&shareId=480000002205486