机器学习之ROC曲线绘制

您所在的位置:网站首页 roc曲线意义 机器学习之ROC曲线绘制

机器学习之ROC曲线绘制

2023-08-06 06:15| 来源: 网络整理| 查看: 265

问题

当我们在使用机器学习分类算法时,例如使用逻辑回归来对鸢尾花进行样本分类, 在这里插入图片描述

是否准确率为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 plt y = 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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3