机器学习之ROC曲线绘制
问题
当我们在使用机器学习分类算法时,例如使用逻辑回归来对鸢尾花进行样本分类,
是否准确率为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精度线确定最优点的步骤:
- 首先得到ISO精度线的斜率 a
- 初始化截距 b=0,即此时的直线方程为y=ax
- 逐渐增大截距,即把直线向左上角移动,直到直线与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曲线绘制相关推荐
- 机器学习之ROC曲线理解
ROC曲线 1.roc曲线 曲线的坐标分别为真正例率(TPR)和假正例率(FPR),定义如下: 真正例的个数是实际值为正例被预测成为正例的值得个数,TPR是预测结果中真正例占实际值中正例的比例: 反正 ...
- 多分类问题的ROC曲线绘制
多分类问题的ROC曲线绘制 目录 多分类问题的ROC曲线绘制 #roc曲线 (1)ROC曲线图中的四个点
- r roc曲线 语言_R语言系列6:生存分析中多重时间依赖性ROC曲线绘制 timeROC
上一篇文章,我们讲到R语言实现Cox回归生存预测模型构建,以及如何将Logistic回归中,多条ROC曲线绘制在一个图里 今天主要围绕生存分析中,预测模型验证部分,如何将多条time-depend e ...
- roc曲线spss怎么做_SPSS单因素ROC曲线及多因素联合诊断ROC曲线绘制(原创手把手) - 医学统计和生物统计讨论版 -丁香园论坛...
最近被好几个师弟师妹问到ROC曲线的绘制,尤其是多因素联合诊断ROC曲线的绘制(如下图这样的怎么做),所以干脆好好总结一下: 一.单因素ROC曲线 其实这个最简单,估计很多人也会,我知道的有两种办法, ...
- python 将多个模型的ROC曲线绘制在一张图里(含图例)
一. 多条ROC曲线绘制函数 def multi_models_roc(names, sampling_methods, colors, X_test, y_test, save=True, dpin ...
- ROC曲线绘制原理即AUC的意义详解
云走雾走走行程,救苦救难救灾星 有求必应,出古洞四海扬名,在深山修真养性 ROC曲线绘制原理即AUC意义详解 ROC曲线绘制原理 ROC曲线常常用来判定一个分类器的分类效果,想要探究ROC曲线的绘制原 ...
- 机器学习之支持向量机SVM之python实现ROC曲线绘制(二分类和多分类)
目录 一.ROC曲线 二.TP.FP.TN.FN 三. python绘制ROC曲线(二分类) 1.思路 2.关键代码 3.完整代码 四. python绘制ROC曲线(多分类) 五.参考文献 一.ROC ...
- 【机器学习】ROC曲线和PR(Precision-Recall)曲线的联系
在机器学习中,ROC(Receiver Operator Characteristic)曲线被广泛应用于二分类问题中来评估分类器的可信度,但是当处理一些高度不均衡的数据集时,PR曲线能表现出更多的信息 ...
- 机器学习中ROC曲线和AUC评估指标
目录 1.真正例率(TPR )与 假正例率(FPR)定义 2.ROC曲线(接受者操作特性曲线,receiver operating characteristic curve) 3.AUC(ROC曲线下 ...
- 基于逻辑回归的癌症分类预测-良/恶性乳腺癌肿瘤预测及ROC曲线绘制
逻辑回归 逻辑回归(Logistic Regression)是机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归.由于算法的简单和高效,在实际中应用非常广泛.逻辑回归是解决二分类问题 ...
最新文章
- 用matlab画曲顶柱体费用数据,数值积分的matlab实现
- whitepages 被关闭_除了滑动关闭APP影响电池寿命,还有哪些操作触碰到了你的知识盲区?...
- Ubuntu下用gcc与nasm联合编译
- linux查看java jdk安装路径和设置环境变量
- Qt中的JSON支持
- ABAP 编程语言中的系统字段(System Fields)
- AEAP的完整形式是什么?
- 《常用控制电路》学习笔记——数控锁相环调速电路
- MongoDb进阶实践之一 如何在Linux系统上安装和配置MongoDB
- sqlserver2005使用convert转换成各种格式的日期
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(10)签到题2题
- 单片机c语言编程实训心得,单片机实训心得体会
- 深入浅出的理解频谱泄露
- 白泽六足机器人导航贴(开源)
- MySQL的基本操作(五)
- Fortigate 飞塔防火墙命令行常用操作 CLI
- 这些大文件传输工具总结,建议外贸人士收藏
- 【PMP】学习笔记 第6章 时间管理
- 京东能成为快手的老铁吗?
- Pandas_C3_分组cheat sheet
热门文章
- Java Bubble Sort 冒泡排序图解
- Android Binder机制
- 抱歉登录伺服务器暂时离线,为什么我离线了,换服务器的时候老提示我重复 – 手机爱问...
- 推荐一个php Zend Guard解密工具 G-DeZender 本地版
- 操作系统原理第五章(资源分配与调度)
- 802.11bgn信道划分及WirelessMon规划频段
- 方正小标宋简体 官方标准版
- java述职报告ppt_java开发人员述职报告.ppt
- 机械设计二级减速器设计
- Android 开发,你遇上 Emoji 头疼吗?