别再只盯着AUC了!用Python手把手教你绘制ROC与PR曲线(附sklearn代码) 超越AUC用Python实战ROC与PR曲线的深度解读在机器学习模型评估的海洋里AUC指标就像一座灯塔指引着无数数据科学家的航向。但真正理解AUC背后的ROC和PR曲线才能让我们在模型优化的航程中不迷失方向。本文将带你用Python代码亲手绘制这两条关键曲线从实践角度揭示它们的差异与应用场景。1. 环境准备与数据加载首先确保你的Python环境已安装以下库!pip install scikit-learn matplotlib numpy pandas我们将使用sklearn内置的乳腺癌数据集作为示例这个二分类数据集非常适合演示ROC和PR曲线from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split data load_breast_cancer() X, y data.data, data.target X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42)提示在实际项目中建议使用stratifyy参数保持训练集和测试集的类别分布一致2. 模型训练与概率预测我们选择逻辑回归作为基础模型因为它能直接输出概率预测这对绘制ROC和PR曲线至关重要from sklearn.linear_model import LogisticRegression model LogisticRegression(max_iter10000) model.fit(X_train, y_train) # 获取测试集的预测概率 y_scores model.predict_proba(X_test)[:, 1] # 取正类的概率理解预测概率的分布对后续分析很有帮助概率区间样本数量占比0.0-0.2158.8%0.2-0.42313.5%0.4-0.63218.8%0.6-0.84526.5%0.8-1.05532.4%3. ROC曲线绘制与解读ROC曲线通过以下代码生成from sklearn.metrics import roc_curve, roc_auc_score import matplotlib.pyplot as plt fpr, tpr, thresholds roc_curve(y_test, y_scores) roc_auc roc_auc_score(y_test, y_scores) plt.figure(figsize(10, 6)) plt.plot(fpr, tpr, colordarkorange, lw2, labelfROC曲线 (AUC {roc_auc:.2f})) plt.plot([0, 1], [0, 1], colornavy, lw2, 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(ROC曲线分析) plt.legend(loclower right) plt.show()关键点解读(0,1)点完美分类器所有正例都被正确识别且没有误报对角线随机猜测的表现基准曲线凸起程度越靠近左上角模型区分能力越强ROC曲线的几个实用观察角度早期识别能力曲线左侧陡峭说明模型能高效识别高置信度正例稳健性曲线平滑表示模型在不同阈值下表现稳定AUC值0.9以上优秀0.8-0.9良好0.7-0.8一般4. PR曲线绘制与场景分析PR曲线特别适合类别不平衡的场景绘制代码如下from sklearn.metrics import precision_recall_curve, average_precision_score precision, recall, thresholds precision_recall_curve(y_test, y_scores) avg_precision average_precision_score(y_test, y_scores) plt.figure(figsize(10, 6)) plt.plot(recall, precision, colorblue, lw2, labelfPR曲线 (AP {avg_precision:.2f})) plt.xlabel(召回率(Recall)) plt.ylabel(精确率(Precision)) plt.title(PR曲线分析) plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.legend(loclower left) plt.show()PR曲线与ROC曲线的关键区别特征ROC曲线PR曲线X轴FPRRecallY轴TPRPrecision基准线对角线(yx)正例比例(水平线)适用场景类别平衡类别不平衡关注点整体分类能力正例识别质量注意当负样本远多于正样本时PR曲线比ROC曲线更能反映模型真实表现5. 阈值选择实战策略通过分析曲线我们可以找到最佳分类阈值# 寻找最佳阈值 - F1分数最大化 from sklearn.metrics import f1_score f1_scores [f1_score(y_test, y_scores t) for t in thresholds] best_threshold thresholds[np.argmax(f1_scores)] print(f最佳F1分数阈值: {best_threshold:.3f}) # 可视化阈值选择 plt.figure(figsize(10, 6)) plt.plot(thresholds, f1_scores[:-1], labelF1分数) plt.axvline(xbest_threshold, colorr, linestyle--, labelf最佳阈值{best_threshold:.3f}) plt.xlabel(阈值) plt.ylabel(F1分数) plt.title(阈值选择分析) plt.legend() plt.show()实际项目中阈值选择应考虑业务需求假阳性与假阴性的代价是否对等资源限制人工复核能力决定可接受的阳性预测数量稳定性避免选择在敏感区域的阈值曲线陡峭处6. 多模型对比可视化比较不同模型的曲线能直观展示性能差异from sklearn.ensemble import RandomForestClassifier # 训练随机森林模型 rf_model RandomForestClassifier(n_estimators100) rf_model.fit(X_train, y_train) rf_scores rf_model.predict_proba(X_test)[:, 1] # 计算两个模型的指标 lr_fpr, lr_tpr, _ roc_curve(y_test, y_scores) rf_fpr, rf_tpr, _ roc_curve(y_test, rf_scores) lr_precision, lr_recall, _ precision_recall_curve(y_test, y_scores) rf_precision, rf_recall, _ precision_recall_curve(y_test, rf_scores) # 绘制对比图 plt.figure(figsize(14, 6)) plt.subplot(1, 2, 1) plt.plot(lr_fpr, lr_tpr, labelf逻辑回归 (AUC{roc_auc_score(y_test, y_scores):.2f})) plt.plot(rf_fpr, rf_tpr, labelf随机森林 (AUC{roc_auc_score(y_test, rf_scores):.2f})) plt.plot([0, 1], [0, 1], k--) plt.xlabel(False Positive Rate) plt.ylabel(True Positive Rate) plt.title(ROC曲线对比) plt.legend() plt.subplot(1, 2, 2) plt.plot(lr_recall, lr_precision, labelf逻辑回归 (AP{average_precision_score(y_test, y_scores):.2f})) plt.plot(rf_recall, rf_precision, labelf随机森林 (AP{average_precision_score(y_test, rf_scores):.2f})) plt.xlabel(Recall) plt.ylabel(Precision) plt.title(PR曲线对比) plt.legend() plt.tight_layout() plt.show()模型对比的关键观察点曲线包络被完全包住的模型明显更差AUC/AP值量化比较的客观指标特定区域表现根据业务需求关注特定区间如高召回率区域7. 高级应用与陷阱规避在实际项目中应用这些曲线时有几个常见陷阱需要注意类别不平衡的应对策略过采样/欠采样调整类别分布使用类别权重参数如class_weightbalanced优先参考PR曲线而非ROC曲线# 使用类别权重的逻辑回归 balanced_model LogisticRegression(class_weightbalanced, max_iter10000) balanced_model.fit(X_train, y_train)交叉验证的曲线绘制更稳健的做法是使用交叉验证绘制平均曲线from sklearn.model_selection import cross_val_predict # 获取交叉验证的预测概率 cv_scores cross_val_predict(LogisticRegression(max_iter10000), X, y, cv5, methodpredict_proba)[:, 1] # 绘制基于交叉验证的曲线 fpr, tpr, _ roc_curve(y, cv_scores) plt.plot(fpr, tpr, labelf交叉验证ROC (AUC{roc_auc_score(y, cv_scores):.2f}))概率校准的重要性某些模型如SVM、随机森林输出的概率需要校准from sklearn.calibration import calibration_curve prob_true, prob_pred calibration_curve(y_test, y_scores, n_bins10) plt.plot(prob_pred, prob_true, markero, label未校准)在医疗诊断项目中我们发现ROC曲线在早期筛查中价值更大而PR曲线在确诊阶段更为关键。一个实用的技巧是将两种曲线结合使用先用ROC确定模型的整体区分能力再用PR曲线优化具体阈值选择。