深挖ROC曲线(截断值计算) – 基于R语言

深挖ROC曲线(截断值计算) – 基于R语言

前言

ROC曲线,多用于二分类问题的评价,通过选取合适的截断值(阈值threshold)便能得出AUC。但很多时候我们只是单纯地通过调包来计算AUC并绘制ROC曲线,其中的原理和最佳阈值的筛选往往被人们忽略。同时笔者最近的项目中需要重新温习这些小细节,故撰文积累一下。(本文不以实际用途出发,若只想得出结果可以看看这篇: ROC曲线基于R语言

混淆矩阵

混淆矩阵是计算Accuracy(准确度),Sensitivity(敏感性, FPR)和Specificity(精确性, TPR)的必经之路。我们通过一个实例来具体阐释混淆矩阵(通过R语言的CrossTable计算所得):

             | prediction
  test$label |         0 |         1 | Row Total |
           1 |         9 |        44 |        53 |
             |     0.170 |     0.830 |     0.525 |

混淆矩阵主要包括以下四个要素:

  • TP :True positive, 代表真正例,预测值和实际值一致且二者都为正例
  • FN:False negative, 代表假负例,预测值和实际值不一致(预测值为负,实际为正)
  • FP:False positive, 代表假正例,预测值和实际值不一致(预测值为正,实际为负)
  • TN:True negative, 代表真负例,预测值和实际值一致且二者都为负例
    在这个例子中我们可以看出:
    TP=44; FN=9; FP=7 ; TN=41

1.通过混淆矩阵计算准确度

深挖ROC曲线(截断值计算) - 基于R语言
深挖ROC曲线(截断值计算) - 基于R语言
深挖ROC曲线(截断值计算) - 基于R语言
一般情况下,只要得出了混淆矩阵,我们便能根据上述公式计算出准确度等分类指标。当然这一切的前提是你得有个像样的混淆矩阵,而这就需要定义截断值了。

; 为什么需要计算截断值

其实这个问题要分情况,并且很多R语言的包避开了这个问题,这里我举例说明:
假设存在两个数组,一个代表预测值,一个代表实际值

     predict test.label
1         1          1
2         0          1
3         1          1
4         1          1
5         1          1
6         0          1

上述是最佳情况,也是我们最希望看到的,因为负例和正例极其明显,仅仅需要判断是1或0便能得出结论。但很可惜的是,很多分类器计算出来的值往往是一个概率值(特别是在随机森林,boosting这类集成学习中),这个时候问题便不再那么简单了:

       p.p1 test.label
1 0.9327975          1
2 0.8683321          1
3 0.9916318          1
4 0.9363141          1
5 0.9975944          1
6 0.9124761          1

上面这个图中,p.p1代表正例的概率,区间在(0,1)间的连续实数。我们无法直观地判断哪一个样本该是正例,哪一个又该是负例。诚然,少数情况下人们图省事会假定阈值为0.5,高于0.5的即是正例,低于0.5的即是负例, 但这种做法在某些情况下会出现极大的偏误,使得我们对模型的性能进行误判(后续举例论证)。故我们需要通过合适方法来计算截断值,并用于AUC的计算。

重点部分:AUC计算和截断值定义

1.何为最佳截断值

通过前文的叙述,我们知道了截断值不能单纯地通过0.5来进行定义,那么何为最佳的截断值,该如何去计算了?目前根据不少R语言的包和论文的查阅,笔者仅总结下述几种方法:

  1. 最大F1值的截断值(F1-optimal threshold) — 来源:h2o包针对AUC的计算
  2. 最大sensitivities+specificities – 来源:R语言机器学习的一本书

在计算截断值时,我们往往需要知道一个图像,即 ROC曲线,这个图以sensitivities和1-specificities为横纵轴,AUC则为曲线围成的面积。可能读者很难将截断值和ROC曲线联想起来,这里通过一个例子阐释:

[thresholds] [sensitivities] [specificities]
[1,]        -Inf    1 0.00000000
[2,] 0.001026790    1 0.02083333
[3,] 0.001237295    1 0.04166667
[4,] 0.001428533    1 0.06250000
[5,] 0.001587942    1 0.08333333
[6,] 0.001710115    1 0.10416667

[97,] 0.9991705 0.09433962    1
[98,] 0.9994262 0.07547170    1
[99,] 0.9994731 0.05660377    1
[100,] 0.9995572 0.03773585   1
[101,] 0.9996690 0.01886792   1
[102,]       Inf 0.00000000   1

第一列是阈值,第二列是sensitivities,第三列是specificitie。随着阈值的逐渐变大(从0-1),我们发现sensitivities在逐渐变小,而specificities在逐渐变大。我们取极端情况考虑,当阈值为0时,大于0的全为正例,即模型能完美的找出所有正例(敏感性=1),但很可惜,所有的负例也被定义为正例,故特异性=0,反之阈值=1时也成立。在正常情况下,我们肯定不愿意让模型瞎猜乱蒙,故我们需要一种均衡(统计优化),类似于方差-残差均衡(但现实情况不一定完全一致),我们希望二者都能 同时达到相对最优的状态。

2.最大F1值的截断值(F1-optimal threshold)

这个方法来自于h2o包中的h2o.auc()函数,F1值能同时考虑sensitivities和specificities,当F1值取得最大值时,便定义该阈值为最佳阈值:

深挖ROC曲线(截断值计算) - 基于R语言
R语言代码如下:

library(pROC)
library(gmodels)
rroc(test$label,p$p1,auc=T,thres=TRUE)

F12*(r$sensitivities*r$specificities)/(r$sensitivities+r$specificities)

ecbind(r$thresholds,F1)
bestsubset(e,e[,2]==max(e[,2]))[,1]
bestas.numeric(best)

p[p$p1<best,]0
p[p$p1>=best,]1
aCrossTable(test$label,p$p1,prop.c = F,prop.t = F,prop.chisq = F)

3.最大sensitivities+specificities

简单粗暴的方法,反正二者加起来最大就行了。个人感觉该方法不太严谨,特别是当模型表现并不佳时,或者通过最大化sensitivities*specificities可能会更加科学。
R语言代码如下:


library(pROC)
library(gmodels)
rroc(test$label,p$p1,auc=T,thres=TRUE)

Sumr$sensitivities+r$specificities

ecbind(r$thresholds,Sum)
bestsubset(e,e[,2]==max(e[,2]))[,1]
bestas.numeric(best)

p[p$p1<best,]0
p[p$p1>=best,]1
aCrossTable(test$label,p$p1,prop.c = F,prop.t = F,prop.chisq = F)

ROC曲线绘制

在解决了截断值的问题后,曲线绘制的问题也就迎刃而解了,ROC曲线是以1-specificities和specificities为横纵轴的,通过上文计算出的数组,我们便能通过简单的plot命令画出ROC曲线:

library(pROC)
library(gmodels)
rroc(test$label,p$p1,auc=T,thres=TRUE)
ecbind(r$thresholds,r$sensitivities,r$specificities)
plot(x=1-e[,2],y=e[,3],type='o')

深挖ROC曲线(截断值计算) - 基于R语言

Original: https://blog.csdn.net/m0_45248682/article/details/115842120
Author: 寂静前行
Title: 深挖ROC曲线(截断值计算) – 基于R语言

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/665009/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球