赞
踩
对于二分类问题,真实的样本标签有两类,我们学习器预测的类别有两类,根据二者的类别组合可以划分为四组,如下表所示:
上表即为混淆矩阵,其中,行表示预测的label值,列表示真实label值。TP,FP,FN,TN分别表示如下意思:
由此可得,TP和TN是我们预测准确的样本,而FP和FN是我们预测错误的样本。
准确率表示的是预测正确的样本数占样本总数的比例。
用混淆矩阵计算的话,准确率可以表示为:
A c c u r a c y = T P + T N T P + F P + T N + F N Accuracy=\frac{TP+TN}{TP+FP+TN+FN} Accuracy=TP+FP+TN+FNTP+TN
对于二分类问题,样本是极其不平衡的。对于大数据集来说,标签为1的正样本数据往往不足10%,那么如果分类器将所有样本判别为负样本,那么仍可以达到90%以上的分类准确率,但这个分类器的性能显然是非常差的。
精确率表示预测结果中,预测为正样本的样本中,正确预测为正样本的概率
召回率表示原始样本中,本就为正样本的样本中,正确预测为正样本的概率。
二者用混淆矩阵表示如下:
P r e c i s i o n = T P T P + F P Precision=\frac{TP}{TP+FP} Precision=TP+FPTP
R e c a l l = T P T P + F N Recall=\frac{TP}{TP+FN} Recall=TP+FNTP
预测一个样本的正负是通过模型给出的概率值和设定的阈值进行比较后得出的,如果模型给出的概率值大于阈值,该样本被预测为正例;如果小于阈值,则被额预测为负例。
我们会将所有的结果按照概率值进行降序排序,这个阈值可以将排序结果截断为两部分。
如果提高阈值,模型会变得很保守,即只有它非常确定一个样本是正例时才会预测为正例,这样能减少假正例(FP)的数量,从而提高精确率。
如果降低阈值,模型更倾向于将样本预测为正例,这样就能减少漏检假负例(FN)的数量,从而提高召回率。
学习到这里,我们会抛出两个问题:
设定阈值后再来计算精确率和召回率太麻烦了,阈值应该被设定为多少?有没有不用设定阈值就可以直接评价模型性能的方法呢?
我们是根据概率值降序排序的结果来划分预测的正负例的,我们要怎样做才能让正例经过模型预测后的概率值都比负例高呢从而来提高模型的性能呢?
没错,ROC与AUC就可以解决以上的两个问题。
ROC
首先,将模型对每个样本预测出来的属于正类的概率值进行降序排序,同时将概率值和标签组合成一个表格。
接着,从排序中最高的概率值开始,逐个将每个样本的概率值视作阈值。对于每个这样的阈值,计算出所有高于或等于此阈值的样本被视为正例,而低于此阈值的样本被视为负例。
对于每个阈值,都需要计算两个关键指标:TPR和FPR
AUC
AUC即为ROC曲线下的面积。
AUC值越接近1,表明模型的性能越好;值越接近0.5(或更低),则表明模型的性能接近(或不如)随机猜测。
为什么要选用这两个公式作为ROC曲线的横纵坐标?
T P R = T P T P + F N TPR=\frac{TP}{TP+FN} TPR=TP+FNTP
F P R = F P T N + F P FPR=\frac{FP}{TN+FP} FPR=TN+FPFP
TPR的分母TP+FN是全部的真实正例数,FPR的分母TN+FP是全部的真实负例数,分母并不会变化。
假设正例的总数为m,负例的总数是n,对按照概率值倒序排序的概率列从上到下设定阈值,每遇到一个真实正例,TPR就增加 1 m \frac{1}{m} m1,每遇到一个真实负例,那么FPR就增加 1 n \frac{1}{n} n1。
AUC可以通过计算ROC积分来得到,但是积分过于麻烦。
因此,我们通过对所有可能的正负样本对,统计其中模型预测得分正确地将正样本得分高于负样本的比例
import numpy as np
from sklearn import metrics
##给定的真实y 和 预测pred
y = np.array([1,0,0,0,1,0,1,0,0,1])
pred = np.array([0.9, 0.4, 0.3, 0.1, 0.35, 0.6, 0.65, 0.32, 0.8, 0.7])
numerator = 0 #分子
denominator = 0 #分母
for i in range(0, len(y)-1):
for j in range(i, len(y)):
if y[i] != y[j]:
denominator += 1
#统计所有正负样本对中,模型把相对位置排序正确的数量
if(y[i]>y[j] and pred[i]>pred[j]) or (y[i]<y[j] and pred[i]<pred[j]):
numerator += 1
print("AUC =" , numerator/denominator)
或者可以用库中的sklearn.metrics.auc(fpr,tpr)
方法
from sklearn import metrics
fpr, tpr, thresholds = metrics.roc_curve(y, pred, pos_label=1)# 真实的标签为y,模型对样本的预测概率为pred,正类的标签是1,fpr是假正率,tpr是真正率,thresholds是阈值
print(metrics.auc(fpr, tpr))# metrics.auc(fpr,tpr)通过对提供的 fpr 和 tpr 数据点进行数值积分(通常使用梯形法则),计算出ROC曲线下的面积。
实的标签为y,模型对样本的预测概率为pred,正类的标签是1,fpr是假正率,tpr是真正率,thresholds是阈值
print(metrics.auc(fpr, tpr))# metrics.auc(fpr,tpr)通过对提供的 fpr 和 tpr 数据点进行数值积分(通常使用梯形法则),计算出ROC曲线下的面积。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。