Python中如何基于5组ROC值的均值与标准差绘制ROC曲线
Python绘制5组结果带误差带ROC曲线实现方案
要画出和参考效果一致的带均值、标准差区间的ROC曲线,不能只存每组的最终AUC值,需要保留每组ROC的FPR/TPR点集,通过插值对齐坐标轴后再计算统计量,具体实现如下:
依赖库准备
先导入需要的工具包:
import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import roc_curve, auc from scipy import interp
核心实现逻辑
- 统一插值基准:因为每组ROC的FPR(假正率)采样点不完全一致,无法直接计算均值,需要先生成0到1区间等距分布的固定FPR网格,把所有组的TPR(真正率)插值到这套统一坐标上。
- 逐组计算指标:遍历5组数据,分别计算每组的FPR、TPR、AUC值,将插值后的TPR结果存入列表。
- 计算统计量:基于对齐后的TPR数组,计算所有组的TPR均值、TPR标准差,同时计算平均AUC和AUC的标准差。
- 分层绘图:先画低透明度的单组ROC作为背景,再画对角随机参考线、平均ROC曲线,最后填充±1标准差的误差区间,添加图例和标注即可匹配参考图效果。
完整可运行代码
# 配置绘图中文显示 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 初始化固定FPR插值轴,取100个等距点 mean_fpr = np.linspace(0, 1, 100) tpr_collect = [] auc_collect = [] # -------------------- # 替换为你自己的5组数据:格式为5个元组,每个元组存(该组真实标签, 模型预测正类概率) # 以下是5折交叉验证的模拟数据,实际使用时删除这部分替换成自己的真实数据即可 from sklearn.datasets import make_classification from sklearn.model_selection import KFold from sklearn.linear_model import LogisticRegression X, y = make_classification(n_samples=1000, n_features=20, random_state=42) kf = KFold(n_splits=5, shuffle=True, random_state=42) cv_dataset = [] for train_idx, test_idx in kf.split(X): clf = LogisticRegression(max_iter=1000).fit(X[train_idx], y[train_idx]) pred_prob = clf.predict_proba(X[test_idx])[:, 1] cv_dataset.append((y[test_idx], pred_prob)) # 模拟数据部分结束 # -------------------- plt.figure(figsize=(8, 8), dpi=100) # 逐组绘制单折ROC for fold_id, (y_true, y_score) in enumerate(cv_dataset): fpr, tpr, _ = roc_curve(y_true, y_score) fold_auc = auc(fpr, tpr) auc_collect.append(fold_auc) # TPR插值对齐 tpr_interp = interp(mean_fpr, fpr, tpr) tpr_interp[0] = 0.0 tpr_collect.append(tpr_interp) # 单折曲线用低透明度细线 plt.plot(fpr, tpr, lw=1, alpha=0.3, label=f'第{fold_id+1}组 ROC (AUC={fold_auc:.2f})') # 计算均值、标准差 mean_tpr = np.mean(tpr_collect, axis=0) mean_tpr[-1] = 1.0 mean_auc_val = auc(mean_fpr, mean_tpr) std_tpr = np.std(tpr_collect, axis=0) tpr_upper_bound = np.minimum(mean_tpr + std_tpr, 1) tpr_lower_bound = np.maximum(mean_tpr - std_tpr, 0) # 绘制参考线、平均曲线、误差带 plt.plot([0, 1], [0, 1], linestyle='--', lw=2, color='gray', label='随机猜测基准', alpha=0.8) plt.plot(mean_fpr, mean_tpr, color='tab:blue', lw=2, label=f'平均ROC (AUC={mean_auc_val:.2f} ± {np.std(auc_collect):.2f})') plt.fill_between(mean_fpr, tpr_lower_bound, tpr_upper_bound, color='tab:blue', alpha=0.2, label='±1 标准差区间') # 图表样式调整 plt.xlim([-0.02, 1.02]) plt.ylim([-0.02, 1.02]) plt.xlabel('假正率 (FPR)', fontsize=12) plt.ylabel('真正率 (TPR)', fontsize=12) plt.title('5组结果ROC曲线', fontsize=14) plt.legend(loc='lower right', fontsize=10) plt.show()
注意事项
- 禁止直接对5组单独计算的AUC值取平均作为平均ROC的AUC,必须先对齐TPR/FPR坐标后再计算平均曲线的AUC,结果才符合统计规范。
- 填充的误差带来自每个FPR点位上TPR的标准差,图例中标注的±值是AUC的标准差,二者不要混淆。
- 单组ROC设置30%左右的透明度,既可以展示所有组的波动情况,又不会干扰平均曲线的展示,和参考图视觉效果一致。
内容的提问来源于stack exchange,提问作者Mark Nguyen
相关产品推荐
相关产品推荐

