python:Sklearn SVM使用留一法时如何绘制ROC曲线与计算AUC

在前面的一篇文章我们给出了使用Sklearn 中的SVM进行分类时如何使用留一法来进行分类。
python基于sklearn的SVM和留一法(LOOCV)进行二分类

如何在使用留一法时绘制ROC曲线和AUC

什么是ROC曲线和AUC?这个可以参考如下的文章。

部分内容摘抄于此
原文链接
https://blog.csdn.net/weixin_45580742/article/details/104500729

  • ROC曲线,全称The Receiver Operating Characteristic Curve,译为受试者操作特性曲线。这是一条以不同阈值下的假正率FPR为横坐标,不同阈值下的召回率Recall为纵坐标的曲线。
  • 我们希望理解,每判断正确一个少数类,就有多少个多数类会被判断错误。假正率正好可以帮助我们衡量这个能力的变化。我们使用Recall和FPR之间的平衡,来替代Recall和Precision之间的平衡,让我们衡量模型在尽量捕捉少数类的时候,误伤多数类的情况如何变化,这就是我们的ROC曲线衡量的平衡。
  • 如果我们是使用decision_function来画ROC曲线,那我们选择出来的最佳阈值其实是最佳距离。
  • 如果我们使用的是概率,我们选取的最佳阈值就会使一个概率值了。
  • 只要我们让这个距离/概率以上的点,都为正类,让这个距离/概率以下的点都为负类,模型就是最好的:即能够捕捉出少数类,又能够尽量不误伤多数类,整体的精确性和对少数类的捕捉都得到了保证。
定义绘制ROC曲线的阈值
  • 通过上述的解释我们可以知道,想要绘制ROC曲线我们需要找到一个最佳阈值
  • 这个阈值的定义有两种方式,分别是使用decision_function定义的距离以及使用predict_proba定义概率这两种方式。本文采用第一种方式decision_function定义。
不使用LOOCV时如何绘制ROC曲线与AUC
  • 不使用LOOCV时我们会有独立的训练集和测试集,当我们得到训练之后的模型.X_train,Y_train(训练集的label);X_test,Y_test(测试集的label);
  • 通过X_train,Y_train 我们可以得到训练模型
  • 将X_test作为模型的输入,可以得到分类结果
  • 简单的代码示例
clf = SVC(kernel='linear', C=1.0)
clf.fit(X_test, Y_test)
Y_prediect = clf.predict(X_test)
  • 如何进一步得到ROC曲线呢,首先使用decision_function得到测试集的分数,这是后面绘制曲线的输入
Y_score = clf.decision_function(X_test)
  • 接下来使用roc_curve, auc计算相关绘制结果。roc_curv的输入分别为测试集的label,和测试集的decision_function计算结果Y_score
from sklearn.metrics import roc_curve, auc
    # 为每个类别计算ROC曲线和AUC
    roc_auc = dict()
    fpr, tpr, threshold = roc_curve(Y_test,Y_score)
    roc_auc = auc(fpr, tpr)
    
  • 在计算结果基础上绘图
	plt.figure()
    lw = 3
    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")
使用LOOCV时SVM的结果怎么绘制ROC和AUC和?
  1. 思考一下,和独立的测试集与训练集相比,留一法的差别在哪里?
    使用留一法时,我们的测试集每次只有一个,测试得到的结果也只有一个,同样通过clf.decision_function(X_test)得到的距离值也只有一个。
  2. 但是我们使用留一法会循环n次,每一次都会得到一个Y_score和一个Y_prediect 。
  3. 上一篇文章python基于sklearn的SVM和留一法(LOOCV)进行二分类中我们将每次的Y_prediect 使用一个list保存下来,最后用于F1,ACC等的计算,同理我们也可以用一个list将每次的Y_score保存下来,最后用于后面绘制AUC和ROC曲线。
代码详解
  • 在上一篇文章的基础上 主要定义保存距离的列表,以及在LOOCV中定义计算每次测试集的Y_score
 Y_score_list = []  
 ....
 loocv代码中
 	Y_score_temp = clf.decision_function(X_test)
 	Y_score_list.append(Y_score_temp)
完整代码
import numpy as np
from sklearn.model_selection import LeaveOneOut
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
import scipy.io as scio



###################功能性函数###################################################
# 将一个任意嵌套的列表整理为一个列表
def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested


# 获取一个预测结果的TP TN FP FN
def get_TpTN_FpFn(list1, list2):
    # list1 为真实的label list2 为预测的label
    reallabel_list = list(flatten(list1))
    predictlabel_list = list(flatten(list2))
    TP_count = 0
    TN_count = 0
    FP_count = 0
    FN_count = 0
    for i in range(len(reallabel_list)):
        if reallabel_list[i] == 1 and predictlabel_list[i] == 1:
            TP_count += 1
        if reallabel_list[i] == -1 and predictlabel_list[i] == -1:
            TN_count += 1
        if reallabel_list[i] == -1 and predictlabel_list[i] == 1:
            FP_count += 1
        if reallabel_list[i] == 1 and predictlabel_list[i] == -1:
            FN_count += 1
    return TP_count, TN_count, FP_count, FN_count


if __name__ == '__main__':
    # ################# 数据的读取与整理了#############################################

    path2 = 'C:\\Users\\Administer\\Desktop\\classer\\dataset'
    MSN_HC = scio.loadmat(path2 + '\\HC_coupling_str_fun_20201022.mat')
    train_data1= MSN_HC['all_coupling'].T
    MSN_GTCS = scio.loadmat(path2 + '\\GTCS_coupling_str_fun.mat')
    train_data2= MSN_GTCS['all_coupling'].T
    # 以上代码按照自己的数据要求输入,可以自己删除。
    dataset = (np.hstack((train_data1, train_data2))).T
    data1_label = list(-1 for i in range(np.size(train_data1, 1)))
    data2_label = list(1 for i in range(np.size(train_data2, 1)))
    datalabels = data1_label + data2_label

    #####################################LOOVC#####################################
    loo = LeaveOneOut()
    loo.get_n_splits(dataset)
    predictlabel_list = []
    reallabel_list = []
    scaler = StandardScaler()
    dataset = scaler.fit_transform(dataset)
    clf = SVC(C=1, kernel='linear', gamma='auto')
    count_right_label = 0
    count = 0  # 循环次数
    # 用留一法进行验证
     Y_score_list = []
    for train_index, test_index in loo.split(dataset):
        X_train, X_test = dataset[train_index], dataset[test_index]
        Y_train, Y_test = np.array(datalabels)[train_index], np.array(datalabels)[test_index]
        clf.fit(X_train, Y_train)
        predictlabel_list.append(list(clf.predict(X_test)))
        reallabel_list.append(list(Y_test))
        #######相比较于前文新增代码
        Y_score_temp = clf.decision_function(X_test)       # 得到的结果为该类到超平面的距离
        Y_score_list.append(Y_score_temp)
        #######
        if Y_test == clf.predict(X_test):
            count_right_label += 1
        count += 1
        print('第{}次循环'.format(count))
    accurancy = count_right_label / len(datalabels)
    print('******循环结束!************')
    print('准确率为:%.2f%%' % (accurancy * 100))
    print('******运行结束!************')

    TP_count, TN_count, FP_count, FN_count = get_TpTN_FpFn(reallabel_list, predictlabel_list)
    F1_score = (2 * TP_count) / (2 * TP_count + FP_count + FN_count)
    ACC = (TP_count + TN_count) / (TP_count + FN_count + TN_count + FP_count)
    SEN = TP_count / (TP_count + FN_count)
    SPE = TN_count / (TN_count + FP_count)

    print('F1_SCORE为:%.2f%%' % (F1_score * 100))
    print('ACC(准确率)为:%.2f%%' % (ACC * 100))
    print('SEN(敏感度)为:%.2f%%' % (SEN * 100))
    print('SPE(特异性)为:%.2f%%' % (SPE * 100))
  # ###############################################
	##绘制ROC和计算AUC
	import matplotlib.pyplot as plt
	from sklearn.metrics import roc_curve, auc
	real = np.array(list(flatten(reallabel_list)))
    roc_auc = dict()
    fpr, tpr, threshold = roc_curve(real, np.array(Y_score_list))
    roc_auc = auc(fpr, tpr)
    plt.figure()
    lw = 3
    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()
结果展示

在这里插入图片描述

后续说明

本文旨在帮助大家快速解决LOOCV情况下绘制ROC与AUC的问题,很多参数都没有细究,大家可以根据自己的课题需要选择。有什么问题欢迎留言讨论,有什么错误也请大家指出,共同学习一起进步!

  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
下面是使用One-Class SVM和交叉验证计算ROC曲线AUC的示例代码: ```python from sklearn.svm import OneClassSVM from sklearn.model_selection import cross_val_score from sklearn.metrics import roc_curve, auc import numpy as np # 构造数据集 X = np.random.randn(100, 10) y = np.ones(100) y[10:20] = -1 # 引入异常样本 # 定义One-Class SVM clf = OneClassSVM(kernel='rbf', gamma=0.1, nu=0.1) # 使用交叉验证计算ROC曲线AUC scores = cross_val_score(clf, X, y, cv=5, scoring='roc_auc') fprs, tprs, thresholds = roc_curve(y, scores) roc_auc = auc(fprs, tprs) # 可视化ROC曲线 import matplotlib.pyplot as plt plt.plot(fprs, tprs, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc) plt.plot([0, 1], [0, 1], color='navy', lw=2, 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') plt.legend(loc="lower right") plt.show() ``` 在上述代码,我们首先构造了一个100个样本、10个特征的数据集。其,前10个样本是异常样本(即y为-1),其余90个样本是正常样本(即y为1)。接着,我们定义了一个rbf核的One-Class SVM,并使用交叉验证计算ROC曲线AUC。最后,我们通过matplotlib对ROC曲线进行了可视化。 需要注意的是,由于One-Class SVM是一种无监督的算法,因此我们无法直接使用sklearn.metricsroc_auc_score函数来计算AUC。在上述代码,我们使用了交叉验证和roc_curve函数来计算ROC曲线AUC

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张小李的风

谢谢老板!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值