机器学习分类性能指标ROC原理及(二分类与多分类)曲线绘制

您所在的位置:网站首页 roc曲线有p值吗 机器学习分类性能指标ROC原理及(二分类与多分类)曲线绘制

机器学习分类性能指标ROC原理及(二分类与多分类)曲线绘制

2023-08-28 22:21| 来源: 网络整理| 查看: 265

文章目录 一、为什么采用ROC作为分类性能指标二、ROC1、roc曲线2、混淆矩阵3、绘制roc曲线 三、二分类ROC曲线绘制四、多分类ROC曲线绘制参考文献

一、为什么采用ROC作为分类性能指标

  既然已经这么多标准,为什么还要使用ROC和AUC呢?因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变换的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现样本类不平衡,即正负样本比例差距较大,而且测试数据中的正负样本也可能随着时间变化。下图是ROC曲线和Presision-Recall曲线的对比,(a)和©为Roc曲线,(b)和(d)为Precision-Recall曲线。 在这里插入图片描述   (a)和(b)展示的是分类其在原始测试集(正负样本分布平衡)的结果,©(d)是将测试集中负样本的数量增加到原来的10倍后,分类器的结果,可以明显的看出,ROC曲线基本保持原貌,而Precision-Recall曲线变化较大。

二、ROC 1、roc曲线

全称为(receiver operating characteristic)接收者操作特征,roc曲线上每个点反映着对同一信号刺激的感受性。

ROC曲线分为横轴和纵轴:

横轴: 负正类率(false postive rate FPR)特异度,划分实例中所有负例占所有负例的比例;(1-Specificity)

纵轴:真正类率(true postive rate TPR)灵敏度,Sensitivity(正类覆盖率)

2、混淆矩阵

  针对一个二分类问题,将实例分成正类(postive)或者负类(negative)。但是实际分类时,会出现如下图四种情况——混淆矩阵。

在这里插入图片描述

若一个实例是正类,并且被预测为正类,即为 真正类(True Postive TP)

若一个实例是正类,但是被预测为负类,即为 假负类(False Negative FN)

若一个实例是负类,但是被预测为正类,即为 假正类(False Postive FP)

若一个实例是负类,并且被预测为负类,即为 真负类(True Negative TN)

由上图可以得到横,纵轴的计算公式:

(1)真正类率(True Postive Rate): T P R = T P ( T P + F N ) TPR=\frac {TP}{(TP+FN)} TPR=(TP+FN)TP​,代表分类器预测的正类中实际正实例占所有正实例的比例。(原本为正的预测为正的比例)Sensitivity (越大越好,1为理想状态)

(2)假正类率(False Postive Rate): F P R = F P ( F P + T N ) FPR=\frac{FP}{(FP+TN)} FPR=(FP+TN)FP​,代表分类器预测的正类中实际负实例占所有负实例的比例。(原本为负的预测为正的比例)(越小越好,0为理想状态)

(3)真负类率(True Negative Rate): T N R = T N ( F P + T N ) TNR=\frac {TN}{(FP+TN)} TNR=(FP+TN)TN​,代表分类器预测的负类中实际负实例占所有负实例的比例。Specificity

(4)假负类率(False Negative Rate): F N R = F N ( T P + F N ) FNR=\frac {FN}{(TP+FN)} FNR=(TP+FN)FN​,代表分类器预测的负类中实际负实例占所有正实例的比例。

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​

a c c u r a c y = T P + T N T P + F N + F P + T N accuracy = \frac{TP+TN}{TP+FN+FP+TN} accuracy=TP+FN+FP+TNTP+TN​

F − m e a s u r e = 2 1 p r e c i s i o n + 1 r e c a l l F-measure = \frac{2}{\frac{1}{precision}+\frac{1}{recall}} F−measure=precision1​+recall1​2​

  假设采用逻辑回归分类器,其给出针对每个实例为正类的概率,那么通过设定一个阈值如0.6,概率大于等于0.6的为正类,小于0.6的为负类。对应的就可以算出一组(FPR,TPR),在平面中得到对应坐标点。随着阈值的逐渐减小,越来越多的实例被划分为正类,但是这些正类中同样也掺杂着真正的负实例,即TPR和FPR会同时增大。阈值最大时,对应坐标点为(0,0),阈值最小时,对应坐标点(1,1)。

  如下面这幅图,图中实线为ROC曲线,线上每个点对应一个阈值。 在这里插入图片描述

  理想目标:TPR=1,FPR=0,即图中(0,1)点,故ROC曲线越靠拢(0,1)点,越偏离45度对角线越好,Sensitivity、Specificity越大效果越好。

  要生成一个ROC曲线,只需要真阳性率(TPR)和假阳性率(FPR)。TPR决定了一个分类器或者一个诊断测试在所有阳性样本中能正确区分的阳性案例的性能。而FPR是决定了在所有阴性的样本中有多少假阳性的判断。ROC曲线中分别将FPR和TPR定义为x和y轴,这样就描述了真阳性(获利)和假阳性(成本)之间的博弈.而TPR就可以定义为灵敏度,而FPR就定义为1-特异度,因此ROC曲线有时候也叫做灵敏度和1-特异度图像.每一个预测结果在ROC曲线中以一个点代表.

  有了ROC曲线后,可以引出AUC的含义:ROC曲线下的面积(越大越好,1为理想状态)

3、绘制roc曲线

  对于一个特定的分类器和测试数据集,每一个实例都会得到一个分类结果,通过统计,利用上述公式,可以得到一组FPR和TPR结果,而要得到一个曲线,实际上需要一系列FPR和TPR的值。那么这一系列值是怎么构造出来的呢?

  在ROC曲线的定义中,有“as its discrimination threshold is varied.”这样一句话,而在本文最开始也提到了分类器的结果可以是“概率输出”,即表示分类器认为某个样本具有多大的概率属于正样本(或负样本),于是如果设置不同的threshold,那么分类结果就会有所变动,因此可以得到一系列FPR和TPR的值。

  接下来就是利用python实现ROC曲线,sklearn.metrics有roc_curve, auc两个函数,本文主要就是通过这两个函数实现二分类和多分类的ROC曲线。

fpr, tpr, thresholds = roc_curve(y_test, scores)

  其中y_test为测试集的结果,scores为模型预测的测试集得分(注意:svm分类器通过decision_function(x_test)计算scores的值)其他的分类器可以这样: (1)probas_=model.predict_proba(X[test]) 可以计算得到每个样本为正例的概率, (2)fpr, tpr, thresholds = roc_curve(y[test], probas_[:, 1]) 该函数传入的参数一定要注意是一列,否则会报错(数组类型错误)该函数则得到我们想要的roc曲线的横纵坐标数组.

  fpr,tpr,thresholds 分别为假正率、真正率和阈值。(应该是不同阈值下的真正率和假正率)。

roc_auc =auc(fpr, tpr)

其中roc_auc为计算的acu的值。

三、二分类ROC曲线绘制

本实例中的数据来源于sklearn中的鸢尾花(iris)数据。

from sklearn import datasets, svm, metrics, model_selection, preprocessing from sklearn.naive_bayes import GaussianNB import matplotlib.pyplot as plt from sklearn.metrics import roc_curve, auc import numpy as np # 导入数据,并且变为2分类 iris = datasets.load_iris() x = iris.data[iris.target !=2, :2] y_ = iris.target[iris.target !=2] y=[] for i in range(len(y_)): y.append(y_[i]+1) y = np.array(y) # Add noisy features to make the problem harder random_state = np.random.RandomState(0) n_samples, n_features = x.shape x = np.c_[x, random_state.randn(n_samples, 200 * n_features)] # 归一化 # x = preprocessing.StandardScaler().fit_transform(x) # 拆分成训练集和测试集 x_train, x_test, y_train, y_test = model_selection.train_test_split(x,y,test_size=0.1, random_state=25) # 构造分类器 clf = svm.SVC(kernel='linear',probability=True,random_state=random_state) clf.fit(x_train, y_train) f1_score = metrics.f1_score(y_test, clf.predict(x_test)) print(f1_score) predict_probs = clf.predict_proba(x_test) y_score = predict_probs[:,1] fpr,tpr,thresholds = metrics.roc_curve(y_test, y_score, pos_label=2) roc_auc = metrics.auc(fpr,tpr) # 计算auc的值 # 绘制roc曲线 plt.figure() lw = 2 plt.figure(figsize=(10,10)) plt.plot(fpr, tpr, color='darkorange',lw=lw,label='LR ROC curve (area = %0.2f)' % roc_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图如下所示: 在这里插入图片描述

四、多分类ROC曲线绘制

  对于多分类问题,ROC曲线的获取主要有两种方法:

  假设测试样本个数为m,类别个数为n。在训练完成后,计算出每个测试样本的在各类别下的概率或置信度,得到一个[m, n]形状的矩阵P,每一行表示一个测试样本在各类别下概率值(按类别标签排序)。相应地,将每个测试样本的标签转换为类似二进制的形式,每个位置用来标记是否属于对应的类别(也按标签排序,这样才和前面对应),由此也可以获得一个[m, n]的标签矩阵L。

①方法一:每种类别下,都可以得到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’的情况。下面参考sklearn官网提供的例子,对两种方法进行实现。

# 引入必要的库 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 = iris.data y = iris.target # 将标签二值化 即:变成[1 0 0] [0 0 1] [0 1 0] 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()

在这里插入图片描述

参考文献

【1】(Fawcett, 2006),Fawcett, T. (2006). An introduction to ROC analysis. Pattern recognition letters, 27(8), 861-874. 【2】Davis, J., & Goadrich, M. (2006, June). The relationship between Precision-Recall and ROC curves. In Proceedings of the 23rd international conference on Machine learning (pp. 233-240). ACM. 【3】ROC和AUC介绍以及如何计算AUC 【4】ROC曲线、AUC、Precision、Recall、F-measure理解及Python实现 【5】ROC曲线 【6】多分类下的ROC曲线和AUC 【7】用Python画ROC曲线 【8】博客:ROC原理介绍及利用python实现二分类和多分类的ROC曲线 【9】博客:https://www.cnblogs.com/kjkj/p/9234986.html



【本文地址】


今日新闻


推荐新闻


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