问题

当我们在使用机器学习分类算法时,例如使用逻辑回归来对鸢尾花进行样本分类,

是否准确率为95%就代表模型非常成功呢?如何来判定我们使用模型的好坏呢?

ROC曲线

其实,这种好坏的评判标准一直都有,而且随着时代的进步不断更迭。

十几年前在《machine learning》一文中就提出了分类精确的概念来划定模型的好坏;此后,学术界又引入信息检索(IR)领域中的recall和precision进行判定。

然而,在现实中样本在不同类别上的不均衡分布(class distribution imbalance problem)使得accuracy这种传统的度量标准不能合理的反映分类器的performance。举个例子:测试样本中有A类样本90个,B 类样本10个。分类器C1把所有的测试样本都分成了A类,分类器C2把A类的90个样本分对了70个,B类的10个样本分对了5个。则C1的分类精度为 90%,C2的分类精度为75%。但是,显然C2更有用些。另外,在一些分类问题中犯不同的错误代价是不同的(cost sensitive learning)。这样,默认0.5为分类阈值的传统做法也显得不恰当了。

为了解决上述问题,人们从医疗分析领域引入了一种新的分类模型performance评判方法——ROC(Receiver Operating Characteristic)分析,其主要分析工具是一个画在二维平面上的曲线——ROC curve。

ROC曲线起源于第二次世界大战时期雷达兵对雷达的信号判断。当时每一个雷达兵的任务就是去解析雷达的信号,但是当时的雷达技术还没有那么先进,存在很多噪声(比如一只大鸟飞过),所以每当有信号出现在雷达屏幕上,雷达兵就需要对其进行破译。有的雷达兵比较谨慎,凡是有信号过来,他都会倾向于解析成是敌军轰炸机,有的雷达兵又比较神经大条,会倾向于解析成是飞鸟。这个时候,雷达兵的上司就很头大了,他急需一套评估指标来帮助他汇总每一个雷达兵的预测信息,以及来评估这台雷达的可靠性。

ROC平面的横坐标是false positive rate(FPR),纵坐标是true positive rate(TPR)。
FPR = FP/N
N是真实负样本的个数,FP是N个负样本中被分类器预测为正样本的个数。
TPR = TP/P
P是真实正样本的个数,TP是P个正样本中被分类器预测为正样本的个数。

对某个分类器而言,我们可以根据其在测试样本上的表现得到一个TPR和FPR点对。这样,此分类器就可以映射成ROC平面上的一个点。通过调整这个分类器分类时候使用的阈值,我们就可以得到一个经过(0, 0),(1, 1)的曲线,这就是此分类器的ROC曲线。一般情况下,这个曲线都应该处于(0, 0)和(1, 1)连线的上方。因为(0, 0)和(1, 1)连线形成的ROC曲线实际上代表的是一个随机分类器。

虽然,用ROC curve来表示分类器的performance很直观好用。可是,人们总是希望通过量化能有一个数值来标志分类器的好坏。于是Area Under roc Curve(AUC)就出现了。顾名思义,AUC的值就是处于ROC curve下方的那部分面积的大小。通常,AUC的值介于0.5到1.0之间,较大的AUC代表了较好的performance。

AUC值对模型性能的判断标准:
AUC = 1,是完美分类器,采用这个预测模型时,存在至少一个阈值能得出完美预测。绝大多数预测的场合,不存在完美分类器。
0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
AUC = 0.5,跟随机猜测一样(例:丢铜板),模型没有预测价值。
AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测。

在这里面会涉及到一些其他的概念,譬如:召回,正确率,特异度等,为了便于理解,详见下表。

ROC曲线的绘制

对于给定的测试数据集及分类器,每一个实例都会得到一个分类结果,类似于一千个人心中有一千个汉姆雷特。通过统计汇总,可以得到一组FPR和TPR结果。分类器认为某个样本具有多大的概率属于正样本(或负样本),于是如果设置不同的threshold,那么分类结果就会有所变动,因此可以得到一系列FPR和TPR的值。

import numpy as np
from sklearn import metrics
import matplotlib.pyplot as plty = np.array([1, 1, 2, 2])
scores = np.array([0.1, 0.4, 0.35, 0.8])fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)# auc的输入为很简单,就是fpr, tpr值
auc = metrics.auc(fpr, tpr)#画图
plt.figure()
lw = 2
plt.plot(fpr, tpr, color='darkorange',lw=lw, label='ROC curve (area = %0.2f)' % auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

这样,二分类的ROC曲线就画好了。然而,如果是多分类怎么办?

有两种方法可以实现。

方法一:每种类别下,都可以得到m个测试样本为该类别的概率(矩阵P中的列)。所以,根据概率矩阵P和标签矩阵L中对应的每一列,可以计算出各个阈值下的假正例率(FPR)和真正例率(TPR),从而绘制出一条ROC曲线。这样总共可以绘制出n条ROC曲线。最后对n条ROC曲线取平均,即可得到最终的ROC曲线。

方法二:
首先,对于一个测试样本:1)标签只由0和1组成,1的位置表明了它的类别(可对应二分类问题中的‘’正’’),0就表示其他类别(‘’负‘’);2)要是分类器对该测试样本分类正确,则该样本标签中1对应的位置在概率矩阵P中的值是大于0对应的位置的概率值的。基于这两点,将标签矩阵L和概率矩阵P分别按行展开,转置后形成两列,这就得到了一个二分类的结果。所以,此方法经过计算后可以直接得到最终的ROC曲线。

上面的两个方法得到的ROC曲线是不同的,当然曲线下的面积AUC也是不一样的。 在python中,方法1和方法2分别对应sklearn.metrics.roc_auc_score函数中参数average值为’macro’和’micro’的情况。

import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp# 加载数据
iris = datasets.load_iris()
X = np.array([1, 1, 2, 2,3,5,6,9])
y = np.array([0.1, 0.4, 0.35, 0.8,0.7,1.2,1.5,1.4])# 将标签二值化
y = label_binarize(y, classes=[0, 1, 2])# 设置种类
n_classes = y.shape[1]# 训练模型并预测
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape# shuffle and split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5,random_state=0)# Learn to predict each class against the other
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True,random_state=random_state))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)# 计算每一类的ROC
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])roc_auc[i] = auc(fpr[i], tpr[i])# Compute micro-average ROC curve and ROC area(方法二)
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])# Compute macro-average ROC curve and ROC area(方法一)
# First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))# Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)
for i in range(n_classes):mean_tpr += interp(all_fpr, fpr[i], tpr[i])# Finally average it and compute AUC
mean_tpr /= n_classes
fpr["macro"] = all_fpr
tpr["macro"] = mean_tpr
roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])# Plot all ROC curves
lw=2
plt.figure()
plt.plot(fpr["micro"], tpr["micro"],label='micro-average ROC curve (area = {0:0.2f})'''.format(roc_auc["micro"]),color='deeppink', linestyle=':', linewidth=4)plt.plot(fpr["macro"], tpr["macro"],label='macro-average ROC curve (area = {0:0.2f})'''.format(roc_auc["macro"]),color='navy', linestyle=':', linewidth=4)colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(n_classes), colors):plt.plot(fpr[i], tpr[i], color=color, lw=lw,label='ROC curve of class {0} (area = {1:0.2f})'''.format(i, roc_auc[i]))plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Some extension of Receiver operating characteristic to multi-class')
plt.legend(loc="lower right")
plt.show()

分类模型优化选择

对于多个分类模型而言,有时会出现ACU相同、模型交叉的情况,这时就需要具体情况具体分析,当需要高Sensitivity值时,A模型好过B;当需要高Specificity值时,B模型好过A。

对于单一模型而言,在同一条ROC曲线上,越靠近 ( 0 , 1 ) (0,1) (0,1)的坐标点对应的模型性能越好,因为此时模型具有较高的真正率和较低的假正率。那么我们如何定量的从一条ROC曲线上找到这个最优的点呢?通常需要借助ISO精度线来找到这个最优的点。

​ISO精度线实际上一类斜率确定而截距不确定的直线,设ISO精度线的方程为 y = a x + b,其中 a为直线的斜率, b为直线的截距。
a = NEG/POS
​其中, NEG为数据集中负样本的数目, POS为数据集中正样本的数目

​ 如下图所示,当 a = 0.5 a=0.5 a=0.5时,图中的红线都可以作为ISO精度线。

​因为ROC曲线上的点都是在同一模型下改变分类阈值得到的,所以在同一条ROC曲线上确定最优点的过程,其实就是确定最佳分类阈值的过程,这个阈值能够让模型在高真正率和低假正率之间取得最好的平衡,即模型的分类性能最好。

根据ISO精度线确定最优点的步骤:

  1. 首先得到ISO精度线的斜率 a
  2. 初始化截距 b=0,即此时的直线方程为y=ax
  3. 逐渐增大截距,即把直线向左上角移动,直到直线与ROC曲线只有一个交点,则这个交点即为我们要找的最优点,这个最优点对应的分类阈值即为使得当前模型性能最优的分类阈值。

参考文献:
https://www.jianshu.com/p/2ca96fce7e81
https://blog.csdn.net/qq_30992103/article/details/99730059
https://www.cnblogs.com/gatherstars/p/6084696.html
https://blog.csdn.net/weixin_39996096/article/details/112317449

机器学习之ROC曲线绘制相关推荐

  1. 机器学习之ROC曲线理解

    ROC曲线 1.roc曲线 曲线的坐标分别为真正例率(TPR)和假正例率(FPR),定义如下: 真正例的个数是实际值为正例被预测成为正例的值得个数,TPR是预测结果中真正例占实际值中正例的比例: 反正 ...

  2. 多分类问题的ROC曲线绘制

    多分类问题的ROC曲线绘制 目录 多分类问题的ROC曲线绘制 #roc曲线 (1)ROC曲线图中的四个点

  3. r roc曲线 语言_R语言系列6:生存分析中多重时间依赖性ROC曲线绘制 timeROC

    上一篇文章,我们讲到R语言实现Cox回归生存预测模型构建,以及如何将Logistic回归中,多条ROC曲线绘制在一个图里 今天主要围绕生存分析中,预测模型验证部分,如何将多条time-depend e ...

  4. roc曲线spss怎么做_SPSS单因素ROC曲线及多因素联合诊断ROC曲线绘制(原创手把手) - 医学统计和生物统计讨论版 -丁香园论坛...

    最近被好几个师弟师妹问到ROC曲线的绘制,尤其是多因素联合诊断ROC曲线的绘制(如下图这样的怎么做),所以干脆好好总结一下: 一.单因素ROC曲线 其实这个最简单,估计很多人也会,我知道的有两种办法, ...

  5. python 将多个模型的ROC曲线绘制在一张图里(含图例)

    一. 多条ROC曲线绘制函数 def multi_models_roc(names, sampling_methods, colors, X_test, y_test, save=True, dpin ...

  6. ROC曲线绘制原理即AUC的意义详解

    云走雾走走行程,救苦救难救灾星 有求必应,出古洞四海扬名,在深山修真养性 ROC曲线绘制原理即AUC意义详解 ROC曲线绘制原理 ROC曲线常常用来判定一个分类器的分类效果,想要探究ROC曲线的绘制原 ...

  7. 机器学习之支持向量机SVM之python实现ROC曲线绘制(二分类和多分类)

    目录 一.ROC曲线 二.TP.FP.TN.FN 三. python绘制ROC曲线(二分类) 1.思路 2.关键代码 3.完整代码 四. python绘制ROC曲线(多分类) 五.参考文献 一.ROC ...

  8. 【机器学习】ROC曲线和PR(Precision-Recall)曲线的联系

    在机器学习中,ROC(Receiver Operator Characteristic)曲线被广泛应用于二分类问题中来评估分类器的可信度,但是当处理一些高度不均衡的数据集时,PR曲线能表现出更多的信息 ...

  9. 机器学习中ROC曲线和AUC评估指标

    目录 1.真正例率(TPR )与 假正例率(FPR)定义 2.ROC曲线(接受者操作特性曲线,receiver operating characteristic curve) 3.AUC(ROC曲线下 ...

  10. 基于逻辑回归的癌症分类预测-良/恶性乳腺癌肿瘤预测及ROC曲线绘制

    逻辑回归 逻辑回归(Logistic Regression)是机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归.由于算法的简单和高效,在实际中应用非常广泛.逻辑回归是解决二分类问题 ...

最新文章

  1. 用matlab画曲顶柱体费用数据,数值积分的matlab实现
  2. whitepages 被关闭_除了滑动关闭APP影响电池寿命,还有哪些操作触碰到了你的知识盲区?...
  3. Ubuntu下用gcc与nasm联合编译
  4. linux查看java jdk安装路径和设置环境变量
  5. Qt中的JSON支持
  6. ABAP 编程语言中的系统字段(System Fields)
  7. AEAP的完整形式是什么?
  8. 《常用控制电路》学习笔记——数控锁相环调速电路
  9. MongoDb进阶实践之一 如何在Linux系统上安装和配置MongoDB
  10. sqlserver2005使用convert转换成各种格式的日期
  11. 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(10)签到题2题
  12. 单片机c语言编程实训心得,单片机实训心得体会
  13. 深入浅出的理解频谱泄露
  14. 白泽六足机器人导航贴(开源)
  15. MySQL的基本操作(五)
  16. Fortigate 飞塔防火墙命令行常用操作 CLI
  17. 这些大文件传输工具总结,建议外贸人士收藏
  18. 【PMP】学习笔记 第6章 时间管理
  19. 京东能成为快手的老铁吗?
  20. Pandas_C3_分组cheat sheet

热门文章

  1. Java Bubble Sort 冒泡排序图解
  2. Android Binder机制
  3. 抱歉登录伺服务器暂时离线,为什么我离线了,换服务器的时候老提示我重复 – 手机爱问...
  4. 推荐一个php Zend Guard解密工具 G-DeZender 本地版
  5. 操作系统原理第五章(资源分配与调度)
  6. 802.11bgn信道划分及WirelessMon规划频段
  7. 方正小标宋简体 官方标准版
  8. java述职报告ppt_java开发人员述职报告.ppt
  9. 机械设计二级减速器设计
  10. Android 开发,你遇上 Emoji 头疼吗?