ROC曲线深度解析:从基础二分类到多分类任务的全方位理解

机器学习关系型数据库数据安全

picture.image

背景

ROC 曲线( Receiver Operating Characteristic curve )是一种广泛用于评价分类模型性能的工具,尤其适用于二分类问题。它通过在不同阈值下计算模型的真阳性率( True Positive Rate, TPR )和假阳性率( False Positive Rate, FPR )来全面评估分类器的表现,随着机器学习的发展,尤其是在医疗诊断、欺诈检测和金融风险控制等领域, ROC 曲线成为衡量分类器性能的标准方法

基本概念

ROC曲线作用

ROC 曲线的主要作用是评估分类模型的性能,其他评估指标(如精度、查准率等)相比, ROC 曲线有以下几个显著的优势:

(1)抗不平衡数据的能力:在处理样本类别不平衡的数据集时,ROC曲线提供了比精度等指标更全面的评价,避免了精度受多数类的偏倚。

(2)不同阈值下的模型性能评估:ROC曲线通过不同的阈值来平衡分类模型的TPR和FPR,可以帮助理解模型在不同的决策点下的表现。

(3)提供AUC值:ROC曲线下的面积(AUC, Area Under the Curve)是一个很好的综合指标,可以通过一个数值直接比较多个模型的优劣。

ROC曲线原理

ROC 曲线的构建原理是基于分类器在不同阈值下的表现,为了详细解释 ROC 的原理,我们可以从二分类问题入手

1

.二分类下的 ROC 原理

在二分类问题中,假设有两个类别:正类( Positive )和负类( Negative ),分类器的输出是一个概率值,通常通过设定阈值来决定输出类别。当阈值发生变化时,模型的性能会随之改变。 ROC 曲线正是在不同阈值下,计算模型的 TPR 和 FPR 来绘制的。

真阳性率( TPR, True Positive Rate ) : 表示被正确预测为正类的正样本占所有正样本的比例,公式为:

其中,

为真阳性,

为假阴性

假阳性率( FPR, False Positive Rate ) : 表示被错误预测为正类的负样本占所有负样本的比例,公式为:

其中,

为假阳性,

为真阴性

ROC 曲线是以 FPR 为横坐标, TPR 为纵坐标绘制的,曲线上的每个点代表一个特定的阈值下分类器的表现。当模型性能较好时, ROC 曲线会靠近左上角,这意味着在高 TPR 的同时保持低 FPR 。

2.AUC值

AUC ( Area Under the Curve )是 ROC 曲线下的面积。 AUC 值介于 0 到 1 之间, AUC 越接近 1 ,模型的区分能力越强。一般情况下, AUC 值可以这样理解

(1)0.5:模型没有区分能力,和随机猜测差不多

(2)0.5-0.7:模型具有较低的区分能力

(3)0.7-0.9:模型具有较好的区分能力

(4)0.9-1.0:模型的区分能力非常强

3.多分类问题中的宏平均ROC曲线

ROC 曲线通常用于二分类问题,但在多分类问题中也有相应的扩展方法。常见的策略有两种:

(1)一对多(One-vs-Rest,OvR):将多分类问题中的每个类别当作正类,其他类别作为负类,分别计算每个类别的ROC曲线,并计算其AUC值。

宏平均 ROC 曲线:首先为每个类别分别计算 ROC 曲线,然后对这些曲线的 TPR 和 FPR 在每个阈值下进行平均,得到宏观的 ROC 曲线。

宏平均 AUC :对所有类别的 AUC 值进行平均,得到一个全局的 AUC 值,衡量多分类模型的整体性能。

(2)一对一(One-vs-One,OvO):在每两个类别之间计算二分类的ROC曲线和AUC值,最后通过一定的加权方式计算整体的AUC。

4.扩展到多分类的宏平均ROC曲线

在多分类问题中, ROC 曲线的构建比较复杂,主要因为我们需要针对每个类别计算一条 ROC 曲线并求平均。宏平均 ROC 的步骤如下:

(1)针对每一个类别,计算它与所有其他类别的ROC曲线,即将该类别视为正类,其他类别视为负类

(2)对于每一类ROC曲线,记录不同阈值下的TPR和FPR

(3)将所有类别的ROC曲线进行平均,得到宏观的ROC曲线

总结

ROC曲线作为分类器评估的经典方法,在处理二分类和多分类问题时都具有广泛的应用。对于二分类问题,ROC曲线能够直观地展示模型的分类能力;在多分类问题中,通过宏平均ROC,可以得到一个全局的评价指标。AUC作为ROC曲线的衍生指标,为模型的比较提供了更简洁有效的方式。

代码实现

二分类模型下的ROC曲线绘制

数据读取


          
import pandas as pd
          
import numpy as np
          
import matplotlib.pyplot as plt
          
plt.rcParams['font.family'] = 'Times New Roman'
          
plt.rcParams['axes.unicode_minus'] = False
          

          
df = pd.read_excel("Breast_Cancer.xlsx")
          
df.head()
      

picture.image

“Breast_Cancer.xlsx” 数据集的来源是UCI机器学习库中的经典数据集之一——乳腺癌威斯康星数据集(Breast Cancer Wisconsin Dataset)。该数据集常用于二分类任务,帮助构建用于乳腺癌诊断的机器学习模型,这里将利用该数据集构建机器学习模型并绘制二分类模型下的ROC曲线

数据分割


          
from sklearn.model_selection import train_test_split
          

          
X = df.drop(['Diagnosis'], axis=1)
          
y = df['Diagnosis']
          

          
# 分割数据集
          
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, 
          
                                                    random_state=42, stratify=df['Diagnosis'])
      

使用train_test_split函数按8:2的比例将特征数据X和目标标签y进行随机划分,其中参数test_size=0.2表示20%数据用于测试集,random_state=42保证分割结果可重复,stratify=df['Diagnosis']则确保按照标签Diagnosis的类别比例进行分层抽样

构建RF模型用于ROC绘制


          
from sklearn.ensemble import RandomForestClassifier
          

          
# 构建随机森林模型,并设置多个参数
          
rf_model = RandomForestClassifier(
          
    n_estimators=100,        # 森林中树的数量,更多的树通常能提高模型的性能,但计算开销也会增加
          
    max_depth=10,            # 树的最大深度,防止树过深导致过拟合。较小的深度可能导致欠拟合
          
    min_samples_split=5,     # 每个节点至少需要有5个样本才能继续分裂,增大可以防止过拟合
          
    min_samples_leaf=2,      # 每个叶子节点至少要有2个样本,防止叶子节点过小导致模型过拟合
          
    max_features='sqrt',     # 每次分裂时考虑的特征数量,'sqrt' 表示使用特征数量的平方根,能提高模型的泛化能力
          
    bootstrap=True,          # 是否在构建每棵树时进行有放回的抽样,True 是默认设置,可以减少模型的方差
          
    oob_score=True,          # 是否使用袋外样本来评估模型的泛化能力,开启此项可以进行无偏验证
          
    random_state=42,         # 保证结果可重复,设置随机数种子
          
    class_weight='balanced'  # 类别权重,适用于样本不均衡的情况,'balanced' 自动调整类别权重
          
)
          

          
# 训练模型
          
rf_model.fit(X_train, y_train)
      

picture.image

使用RandomForestClassifier 构建并训练随机森林模型,其中设置了参数如n_estimators=100(树的数量)、max_depth=10(最大深度)、min_samples_split=5(最小分裂样本数)、class_weight='balanced'(平衡类别权重)等,以避免过拟合并应对类别不平衡,模型训练完成后才能基于其预测概率绘制ROC曲线来评估分类器的性能

ROC绘制


          
from sklearn.metrics import roc_curve, auc
          
# 预测概率
          
y_score = rf_model.predict_proba(X_test)[:, 1]
          

          
# 计算ROC曲线
          
fpr_rf, tpr_rf, _ = roc_curve(y_test, y_score)
          
roc_auc_rf = auc(fpr_rf, tpr_rf)
          

          
# 绘制ROC曲线
          
plt.figure(dpi=1200)
          
plt.plot(fpr_rf, tpr_rf, color='darkorange', lw=2, label='ROC curve (area = %0.4f)' % roc_auc_rf)
          
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.savefig("Receiver Operating Characteristic_1.pdf", bbox_inches='tight')
          
plt.show()
      

picture.image

通过predict_proba获取测试集的预测概率后,使用roc_curve计算假阳性率(FPR)和真阳性率(TPR),再通过auc计算ROC曲线下面积(AUC),并绘制ROC曲线图,其中参数如color='darkorange'设置曲线颜色,lw=2指定线宽,最后将图表保存为PDF文件以便后续使用,橙色曲线:表示模型的ROC曲线。曲线越接近左上角,说明模型的性能越好。这个模型的曲线几乎贴近左上角,说明分类效果非常好,蓝色虚线:表示随机分类器的表现(即随机猜测的模型),它是一条对角线,AUC值为0.5。相比之下,橙色曲线明显优于随机分类,AUC值(Area Under the Curve)= 0.9967:曲线下面积(AUC)为0.9967,接近1,这表示模型在区分正负类上非常强,几乎可以完美地将正类和负类分开。

同画布下多个模型ROC绘制


          
from sklearn.svm import SVC
          
from sklearn.tree import DecisionTreeClassifier
          

          
# 训练决策树模型
          
dt_model = DecisionTreeClassifier()
          
dt_model.fit(X_train, y_train)
          
y_score_dt = dt_model.predict_proba(X_test)[:, 1]
          
fpr_dt, tpr_dt, _ = roc_curve(y_test, y_score_dt)
          
roc_auc_dt = auc(fpr_dt, tpr_dt)
          

          
# 训练SVM模型
          
svm_model = SVC(probability=True)
          
svm_model.fit(X_train, y_train)
          
y_score_svm = svm_model.predict_proba(X_test)[:, 1]
          
fpr_svm, tpr_svm, _ = roc_curve(y_test, y_score_svm)
          
roc_auc_svm = auc(fpr_svm, tpr_svm)
          

          
# 绘制ROC曲线
          
plt.figure(dpi=1200)
          
plt.plot(fpr_svm, tpr_svm, color='purple', lw=2, label='SVM ROC curve (area = %0.4f)' % roc_auc_svm)
          
plt.plot(fpr_rf, tpr_rf, color='red', lw=2, label='Random Forest ROC curve (area = %0.4f)' % roc_auc_rf)
          
plt.plot(fpr_dt, tpr_dt, color='blue', lw=2, label='Decision Tree ROC curve (area = %0.4f)' % roc_auc_dt)
          
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.savefig("Receiver Operating Characteristic_2.pdf", bbox_inches='tight')
          
plt.legend(loc="lower right")
          
plt.show()
          

      

picture.image

同样的道理再次训练两个基础模型(决策树、支持向量机(SVM)),分别训练后计算它们的ROC曲线,并将它们绘制在同一个图表上以便比较它们的分类性能,该图展示了三个模型(SVM、随机森林、决策树)的ROC曲线,其中随机森林的AUC值最高(0.9967),表现最佳;SVM的AUC值为0.9808,性能也较好;而决策树的AUC值为0.9058,相对较低,模型表现稍逊。整体来看,随机森林在这个分类任务中效果最优。

多分类模型下的宏平均ROC曲线绘制

数据读取


          
import pandas as pd
          
import numpy as np
          
import matplotlib.pyplot as plt
          
plt.rcParams['font.family'] = 'Times New Roman'
          
plt.rcParams['axes.unicode_minus'] = False
          

          
df = pd.read_excel("heart.xlsx")
          
df.head()
      

picture.image

该数据集是来自UCI机器学习库的经典心脏病数据集(Heart Disease Dataset)。该数据集用于预测是否存在心脏病,并且标签变量(num 列)包含多个类别,属于一个多分类任务,接下来将利用这个数据集构建机器学习模型,用其绘制宏平均ROC曲线

数据分割


          
from sklearn.model_selection import train_test_split
          

          
X = df.drop(['num'], axis=1)
          
y = df['num']
          

          
# 分割数据集
          
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, 
          
                                                    random_state=42, stratify=df['num'])
      

使用train_test_split函数将特征数据X和目标标签y按8:2的比例划分为训练集和测试集,其中test_size=0.2表示20%的数据用于测试,random_state=42确保分割结果可重复,stratify=df['num']根据标签num的类别比例进行分层抽样

构建RF模型用于宏平均ROC绘制


          
from sklearn.ensemble import RandomForestClassifier
          

          
# 构建随机森林模型,并设置多个参数
          
rf_model = RandomForestClassifier(
          
    n_estimators=100,        # 森林中树的数量,更多的树通常能提高模型的性能,但计算开销也会增加
          
    max_depth=10,            # 树的最大深度,防止树过深导致过拟合。较小的深度可能导致欠拟合
          
    min_samples_split=5,     # 每个节点至少需要有5个样本才能继续分裂,增大可以防止过拟合
          
    min_samples_leaf=2,      # 每个叶子节点至少要有2个样本,防止叶子节点过小导致模型过拟合
          
    max_features='sqrt',     # 每次分裂时考虑的特征数量,'sqrt' 表示使用特征数量的平方根,能提高模型的泛化能力
          
    bootstrap=True,          # 是否在构建每棵树时进行有放回的抽样,True 是默认设置,可以减少模型的方差
          
    oob_score=True,          # 是否使用袋外样本来评估模型的泛化能力,开启此项可以进行无偏验证
          
    random_state=42,         # 保证结果可重复,设置随机数种子
          
    class_weight='balanced'  # 类别权重,适用于样本不均衡的情况,'balanced' 自动调整类别权重
          
)
          

          
# 训练模型
          
rf_model.fit(X_train, y_train)
      

picture.image

通过设置参数构建随机森林模型RandomForestClassifier,并使用训练数据X_train和y_train进行模型训练,以便后续用于计算宏平均ROC曲线并绘制其性能表现

计算多分类任务的宏平均ROC与AUC


          
from sklearn import metrics
          
from sklearn.preprocessing import label_binarize
          
# 预测并计算概率
          
ytest_proba_rf = rf_model.predict_proba(X_test)
          

          
# 将y标签转换成one-hot形式
          
ytest_one_rf = label_binarize(y_test, classes=[0, 1, 2])
          

          
# 宏平均法计算AUC
          
rf_AUC = {}
          
rf_FPR = {}
          
rf_TPR = {}
          

          
for i in range(ytest_one_rf.shape[1]):
          
    rf_FPR[i], rf_TPR[i], thresholds = metrics.roc_curve(ytest_one_rf[:, i], ytest_proba_rf[:, i])
          
    rf_AUC[i] = metrics.auc(rf_FPR[i], rf_TPR[i])
          
print(rf_AUC)
          

          
# 合并所有的FPR并排序去重
          
rf_FPR_final = np.unique(np.concatenate([rf_FPR[i] for i in range(ytest_one_rf.shape[1])]))
          

          
# 计算宏平均TPR
          
rf_TPR_all = np.zeros_like(rf_FPR_final)
          
for i in range(ytest_one_rf.shape[1]):
          
    rf_TPR_all += np.interp(rf_FPR_final, rf_FPR[i], rf_TPR[i])
          
rf_TPR_final = rf_TPR_all / ytest_one_rf.shape[1]
          

          
# 计算最终的宏平均AUC
          
rf_AUC_final = metrics.auc(rf_FPR_final, rf_TPR_final)
          
AUC_final_rf = rf_AUC_final  # 最终AUC
          

          
print(f"Macro Average AUC with Random Forest: {AUC_final_rf}")
      

picture.image

通过将多分类标签转换为One-hot编码形式,计算每个类别的ROC曲线和AUC值,然后合并各类别的假阳性率(FPR)并插值计算出宏平均真阳性率(TPR),最终使用宏平均法计算出随机森林模型在多分类任务下的整体ROC曲线和宏平均AUC值,以评估模型的综合分类性能,类别0的AUC值为 0.9372,表示模型在该类别上的分类性能非常好,类别1的AUC值为 0.5982,表示模型在该类别上的分类效果较差,类别2的AUC值为 0.7672,表示模型在该类别上的分类效果较为中等,最终的宏平均AUC为 0.7818,表示在所有类别上,模型整体的分类性能还算不错,但在类别1上的表现较弱,拉低了整体的平均表现

宏平均ROC绘制


          
plt.figure(figsize=(10, 10), dpi=1200)
          
# 使用不同的颜色和线型
          
plt.plot(rf_FPR[0], rf_TPR[0], color='#1f77b4', linestyle='-', label='Class 0 ROC  AUC={:.4f}'.format(rf_AUC[0]), lw=2)
          
plt.plot(rf_FPR[1], rf_TPR[1], color='#ff7f0e', linestyle='-', label='Class 1 ROC  AUC={:.4f}'.format(rf_AUC[1]), lw=2)
          
plt.plot(rf_FPR[2], rf_TPR[2], color='#2ca02c', linestyle='-', label='Class 2 ROC  AUC={:.4f}'.format(rf_AUC[2]), lw=2)
          
# 宏平均ROC曲线
          
plt.plot(rf_FPR_final, rf_TPR_final, color='#000000', linestyle='-', label='Macro Average ROC  AUC={:.4f}'.format(rf_AUC_final), lw=3)
          
# 45度参考线
          
plt.plot([0, 1], [0, 1], color='gray', linestyle='--', lw=2, label='45 Degree Reference Line')
          
plt.xlabel('False Positive Rate (FPR)', fontsize=15)
          
plt.ylabel('True Positive Rate (TPR)', fontsize=15)
          
plt.title('Random Forest Classification ROC Curves and AUC', fontsize=18)
          
plt.grid(linestyle='--', alpha=0.7)
          
plt.legend(loc='lower right', framealpha=0.9, fontsize=12)
          
plt.savefig('RF_optimized.pdf', format='pdf', bbox_inches='tight')
          
plt.show()
      

picture.image

这里绘制随机森林模型在多分类任务中的ROC曲线,包括每个类别的ROC曲线、宏平均ROC曲线以及随机猜测的参考线,图中还显示了每个类别及宏平均的AUC值,用于评估模型的分类性能,具体解释前文已给出

往期推荐

SCI图表复现:整合数据分布与相关系数的高级可视化策略

复现顶刊Streamlit部署预测模型APP

树模型系列:如何通过XGBoost提取特征贡献度

SHAP进阶解析:机器学习、深度学习模型解释保姆级教程

特征选择:Lasso和Boruta算法的结合应用

从基础到进阶:优化SHAP力图,让样本解读更直观

SCI图表复现:优化SHAP特征贡献图展示更多模型细节

多模型中的特征贡献度比较与可视化图解

基于SHAP值的 BorutaShap 算法在特征选择中的应用与优化

基于相关性与标准差的多模型评价指标可视化比较 —— 泰勒图应用解析

picture.image

picture.image

picture.image

微信号|deep_ML

欢迎添加作者微信进入Python、ChatGPT群

进群请备注Python或AI进入相关群

无需科学上网、同步官网所有功能、使用无限制

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参考

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
大规模高性能计算集群优化实践
随着机器学习的发展,数据量和训练模型都有越来越大的趋势,这对基础设施有了更高的要求,包括硬件、网络架构等。本次分享主要介绍火山引擎支撑大规模高性能计算集群的架构和优化实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论