一、ROC曲线
定义可见:
作用:通过ROC曲线可以获取相关性能指标,如EER、AUC等,这些性能指标可以用来评价一个SVM训练出来模型的优劣
二、TP、FP、TN、FN
三、 python绘制ROC曲线(二分类)
1、思路
python主要的思路是通过roc_curve函数和测试样本的实际标签集test_label、由训练模型预测得到的标签集test_predict_label获得。通过比对实际标签和预测标签来计算TP、FP、TN、FN,通过roc_curve函数可以实现,返回的是TP、FP、以及阈值threshold。计算ROC曲线只需要TPFP即可。
2、关键代码
................
#train_data用于训练的样本集, test_data用于测试的样本集, train_label训练样本对应的标签集, test_label测试样本对应的标签集
###通过decision_function()计算得到的test_predict_label的值,用在roc_curve()函数中
test_predict_label = svm.fit(train_data, train_label).decision_function(test_data)
#首先通过fit来对训练样本和训练样本标签进行训练得到模型,然后通过decision_function来获得模型对于测试样本集预测的标签集
# Compute ROC curve and ROC area for each class#计算tp,fp
#通过测试样本输入的标签集和模型预测的标签集进行比对,得到fp,tp,不同的fp,tp是算法通过一定的规则改变阈值获得的
fpr,tpr,threshold = roc_curve(test_label, test_predict_label) ###计算真正率和假正率
roc_auc = auc(fpr,tpr) ###计算auc的值,auc就是曲线包围的面积,越大越好
..................
#test_predict_label
[ 0.17284263 0.65445393 -0.54087101 0.3555818 0.00579262 -0.20174248
0.0565328 0.00571205 -0.1517872 0.25656427 0.39764688 0.04549989
0.33455816 -0.12499602 0.23724787 -0.36250412 -0.0874348 -0.11575856
-0.25270656 -0.23457408 -0.18239472 -0.10728706 -0.32201471 0.71954289
-0.29292995 -0.22073314 -0.32473373 -0.19383585 -0.24296148 0.37524795]
在二分类问题中,阈值的改变其实就是相当于从一个边界移动到另一个边界,阈值的改变也就使得tp和fp的改变
#阈值threshold
[ 1.71954289 0.71954289 0.25656427 0.0565328 0.00571205 -0.0874348
-0.10728706 -0.12499602 -0.1517872 -0.18239472 -0.20174248 -0.23457408
-0.24296148 -0.54087101]
#tp
[0. 0. 0. 0.2 0.2 0.26666667
0.26666667 0.4 0.4 0.46666667 0.46666667 0.6
0.6 1. ]
#fp
[0. 0.06666667 0.46666667 0.46666667 0.66666667 0.66666667
0.73333333 0.73333333 0.8 0.8 0.93333333 0.93333333
1. 1. ]
3、完整代码
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc ###计算roc和auc
from sklearn import model_selection
# Import some data to play with
iris = datasets.load_iris()
X = iris.data#得到样本集
y = iris.target#得到标签集
##变为2分类
X, y = X[y != 2], y[y != 2]#通过取y不等于2来取两种类别
# 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)]
# shuffle and split training and test sets划分样本集
train_data, test_data, train_label, test_label = model_selection.train_test_split(X, y, test_size=.3,random_state=0)
#train_data用于训练的样本集, test_data用于测试的样本集, train_label训练样本对应的标签集, test_label测试样本对应的标签集
# Learn to predict each class against the other分类器设置
svm = svm.SVC(kernel='linear', probability=True,random_state=random_state)#使用核函数为线性核,参数默认,创建分类器
###通过decision_function()计算得到的test_predict_label的值,用在roc_curve()函数中
test_predict_label = svm.fit(train_data, train_label).decision_function(test_data)
#首先通过fit来对训练样本和训练样本标签进行训练得到模型,然后通过decision_function来获得模型对于测试样本集预测的标签集
print(test_predict_label)
# Compute ROC curve and ROC area for each class#计算tp,fp
#通过测试样本输入的标签集和模型预测的标签集进行比对,得到fp,tp,不同的fp,tp是算法通过一定的规则改变阈值获得的
fpr,tpr,threshold = roc_curve(test_label, test_predict_label) ###计算真正率和假正率
print(fpr)
print(tpr)
print(threshold)
roc_auc = auc(fpr,tpr) ###计算auc的值,auc就是曲线包围的面积,越大越好
plt.figure()
lw = 2
plt.figure(figsize=(10,10))
plt.plot(fpr, tpr, color='darkorange',
lw=lw, label='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()
虚线表示auc为0.5,正确率与错误率一样的情况
四、 python绘制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
# 将标签二值化
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()
五、参考文献
《ROC原理介绍及利用python实现二分类和多分类的ROC曲线》
ROC曲线、AUC、Precision、Recall、F-measure理解及Python实现
ROC曲线
多分类下的ROC曲线和AUC
用Python画ROC曲线
任何程序错误,以及技术疑问或需要解答的,请添加
Original: https://blog.csdn.net/sinat_28371057/article/details/113749034
Author: 青年夏日科技
Title: 机器学习之支持向量机SVM之python实现ROC曲线绘制(二分类和多分类)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/665434/
转载文章受原作者版权保护。转载请注明原作者出处!