为何OneVsRestClassifier(XGBoost)用pred_proba算的ROC_AUC优于pred结果?
多分类OneVsRest+XGBoost场景下predict与predict_proba计算AUC结果差异解释
问题描述
处理6分类任务时,基于训练完成的OneVsRestClassifier(XGBoost)分类器,使用Scikit-Learn计算各类别ROC曲线下面积(AUC)时可观测到:传入predict_proba()输出的预测概率数组计算得到的各类别AUC,显著高于传入predict()输出的硬预测结果的计算值。
两类计算方式的代码与对应结果如下:
# 方式1:传入predict_proba输出的概率值计算 y_pred = predictor.predict_proba(X_test_outer_loop) roc_auc = dict() for i in range(len(classes)): # 6分类任务 fpr[i], tpr[i], _ = roc_curve(y_test.iloc[:, i], y_pred[:, i]) roc_auc[i] = auc(fpr[i], tpr[i]) # 对应各类别AUC结果 # 0: 0.5774, 1: 0.8212, 2: 0.6990, 3: 0.4842, 4: 0.5747, 5: 0.4059
# 方式2:传入predict输出的硬预测结果计算 y_pred = predictor.predict(X_test_outer_loop) roc_auc = dict() for i in range(len(classes)): # 6分类任务 fpr[i], tpr[i], _ = roc_curve(y_test.iloc[:, i], y_pred[:, i]) roc_auc[i] = auc(fpr[i], tpr[i]) # 对应各类别AUC结果 # 0: 0.4905, 1: 0.4924, 2: 0.6262, 3: 0.4701, 4: 0.4954, 5: 0.4663
原有认知为predict_proba()最终也是选取最高预测概率对应的类别,和predict()用于ROC生成的逻辑一致,已知二分类下阈值调整会影响指标,但无法理解OneVsRest多分类场景出现该差异的原因。
原因解释
- AUC的计算依赖连续的决策分数输入:ROC曲线的绘制逻辑是遍历决策分数从高到低的所有可能切分阈值,依次计算每个阈值下的假阳性率、真阳性率,连接所有点形成曲线后计算线下面积。AUC的本质含义是「随机抽取一个正样本、一个负样本,模型给正样本的决策分数高于负样本的概率」,衡量的是模型对样本的排序能力,必须输入连续值才能得到正确结果。
- 传入
predict_proba()结果是AUC计算的正确用法:predict_proba()输出的是0~1之间的连续概率值,roc_curve可以遍历所有概率阈值画出完整的ROC曲线,计算得到的AUC能真实反映每个OneVsRest二分类器对当前类别的排序能力。 - 传入
predict()硬预测结果得到的AUC无实际参考价值:predict()输出的是0/1离散标签(仅标记样本是否被判定为某类),此时roc_curve最多只能找到3个有效坐标点:(0,0)、(默认argmax决策规则下的FPR/TPR点)、(1,1),根本无法绘制完整ROC曲线,算出来的“面积”只是默认阈值下单点分类性能的线性映射,完全丢失了概率包含的排序信息,结果自然会显著偏低,大量类别结果接近0.5(随机猜水平)是这类错误计算的典型表现。 - OneVsRest结构不改变该逻辑:不管是单模型多分类还是OneVsRest多分类,
predict()取最高概率类的规则本质是给每个类别的二分类决策设置了一个随其他类别概率动态变化的阈值,拿这个阈值下的离散0/1结果算AUC,本质是只测了一个阈值点的性能,和AUC的设计目标完全不符,和OneVsRest包含几个基评估器没有关系。
注:计算多分类AUC时,永远不要传入
predict()输出的离散硬标签,必须传入predict_proba()输出的连续概率或者decision_function()输出的连续决策分数。
内容的提问来源于stack exchange,提问作者Leon J
相关产品推荐
相关产品推荐

