Python中多分类任务的ROC/CAP曲线绘制问题求助
嘿,我刚好在多分类任务里踩过ROC和CAP曲线绘制的坑,给你整理了两个实用的解决方案,附带直接能跑的Python代码,你可以直接套用到自己的数据集上!
一、多分类ROC曲线的绘制
多分类任务里的ROC曲线主要有两种常用的实现思路:One-vs-Rest(OvR,一对其余)和One-vs-One(OvO,一对一)。其中OvR因为直观易懂,是我平时做项目用得最多的方式。
1. One-vs-Rest(OvR)方法
原理
把每个类别单独当作“正类”,剩下的所有类别合并成“负类”,然后为每个类别生成一条二分类ROC曲线,最后把所有曲线画在同一张图里,就能清晰对比每个类别的区分能力。
代码实现
import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import roc_curve, auc from sklearn.preprocessing import label_binarize # 1. 加载示例数据集(替换成你自己的X和y即可) iris = datasets.load_iris() X = iris.data y = iris.target # 2. 将标签二值化(OvR需要每个类别对应一个二分类标签) y_bin = label_binarize(y, classes=[0, 1, 2]) n_classes = y_bin.shape[1] # 3. 拆分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y_bin, test_size=0.3, random_state=42) # 4. 训练分类器(这里用随机森林,你可以换成SVM、XGBoost等支持概率输出的模型) clf = RandomForestClassifier(n_estimators=100, random_state=42) clf.fit(X_train, y_train) # 5. 获取每个类别的预测概率 y_score = clf.predict_proba(X_test) # 6. 计算每个类别的FPR、TPR和AUC值 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]) # 7. 绘制所有类别的ROC曲线 plt.figure(figsize=(8, 6)) colors = ['blue', 'red', 'green'] for i, color in zip(range(n_classes), colors): plt.plot(fpr[i], tpr[i], color=color, lw=2, label=f'ROC curve of class {i} (AUC = {roc_auc[i]:.2f})') # 绘制随机猜测的基准线 plt.plot([0, 1], [0, 1], 'k--', lw=2) plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Multi-class ROC Curve (One-vs-Rest)') plt.legend(loc="lower right") plt.show()
小提示
- 如果你用的是自己的数据集,只需要替换
X和y即可,label_binarize会自动处理整数或字符串类型的标签。 - 如果你的模型不支持
predict_proba(比如部分SVM模型),可以用decision_function代替获取分类得分。
2. One-vs-One(OvO)方法
原理
每两个类别之间都做一次二分类ROC曲线,比如3个类别会生成3条曲线(0vs1、0vs2、1vs2)。这种方法更细致,但曲线数量会随类别数激增(k个类别会有k*(k-1)/2条曲线),适合类别数较少的场景。
代码实现(简略版)
from sklearn.multiclass import OneVsOneClassifier # 用OneVsOneClassifier包装模型 ovo_clf = OneVsOneClassifier(RandomForestClassifier(n_estimators=100, random_state=42)) ovo_clf.fit(X_train, y.argmax(axis=1)) # 以类别0和1为例绘制OvO的ROC曲线 mask = (y_test.argmax(axis=1) == 0) | (y_test.argmax(axis=1) == 1) X_ovo = X_test[mask] y_ovo = y_test[mask].argmax(axis=1) y_ovo_score = ovo_clf.predict_proba(X_ovo)[:, 0] # 取类别0的预测概率 fpr_ovo, tpr_ovo, _ = roc_curve(y_ovo, y_ovo_score, pos_label=0) roc_auc_ovo = auc(fpr_ovo, tpr_ovo) plt.figure(figsize=(8,6)) plt.plot(fpr_ovo, tpr_ovo, lw=2, label=f'ROC curve (Class 0 vs 1, AUC={roc_auc_ovo:.2f})') plt.plot([0,1],[0,1],'k--') plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('One-vs-One ROC Curve') plt.legend() plt.show()
二、多分类CAP曲线的绘制
CAP曲线(Cumulative Accuracy Profile)用来评估模型对样本的排序能力——简单说就是看“按预测概率从高到低排序后,前N%的样本里能抓到多少真实正样本”,比ROC更直观反映模型的排序效果。
原理
针对每个类别:
- 把测试集样本按属于该类别的预测概率从高到低排序。
- 计算累计的真实正样本数量占总正样本数的比例。
- 和随机模型(直线)、完美模型(阶梯线)对比,就能看出模型的性能差距。
代码实现
import numpy as np def plot_cap_curve(y_true, y_score, class_name): # 1. 按预测概率从高到低排序样本 sorted_indices = np.argsort(y_score)[::-1] y_true_sorted = y_true[sorted_indices] y_score_sorted = y_score[sorted_indices] # 2. 计算累计正样本数和累计样本数 total_pos = np.sum(y_true) cumulative_pos = np.cumsum(y_true_sorted) cumulative_samples = np.arange(1, len(y_true)+1) # 3. 计算CAP曲线的纵坐标(累计正样本比例) cap_curve = cumulative_pos / total_pos if total_pos !=0 else np.zeros_like(cumulative_samples) # 4. 绘制三条曲线:模型、完美、随机 plt.figure(figsize=(8,6)) plt.plot(cumulative_samples / len(y_true), cap_curve, lw=2, label='Model CAP Curve') plt.plot([0, total_pos/len(y_true), 1], [0, 1, 1], 'g--', lw=2, label='Perfect Model') plt.plot([0,1], [0,1], 'k--', lw=2, label='Random Model') plt.xlabel('Proportion of Samples Selected') plt.ylabel('Proportion of True Positives Captured') plt.title(f'CAP Curve for Class {class_name}') plt.legend(loc='lower right') plt.show() # 为每个类别绘制CAP曲线 for i in range(n_classes): plot_cap_curve(y_test[:,i], y_score[:,i], class_name=i)
小提示
- 如果某个类别在测试集里没有正样本,函数会自动处理避免除以0的错误。
- 从CAP曲线里能快速看出:模型曲线越靠近完美模型,排序能力越强;越靠近随机模型,性能越差。
内容的提问来源于stack exchange,提问作者Sai Shree
相关产品推荐
相关产品推荐

