roc_auc_score与scoring=roc_auc的cross_val_score结果差异原因
造成两类AUC计算结果差异的核心原因
首先明确:cross_val_score中设置scoring='roc_auc'的底层计算逻辑,和直接调用roc_auc_score完全一致,二者不存在算法实现上的区别,结果差距完全来自代码写法错误、评估数据集差异两个核心问题:
1. 代码2的AUC计算写法存在致命错误
roc_auc_score计算ROC曲线下面积,需要输入模型输出的正类预测概率作为得分输入,通过遍历0到1之间所有分类阈值计算对应TPR、FPR,最终围成AUC值。
你在代码2中传入的是lrmodel.predict(X_test)的返回值,这个接口输出的是默认阈值0.5下的0/1硬分类标签,相当于只给ROC空间提供了一个固定分类点,根本无法计算完整ROC曲线,算出来的0.67是完全错误的无效值。
正确写法应该传入正类预测概率:
lrmodel = LogisticRegression(class_weight='balanced') lrmodel.fit(X_train, y_train) # 取预测结果中标签为1的概率列作为得分输入 lr_auc = roc_auc_score(y_test, lrmodel.predict_proba(X_test)[:, 1])
2. 两段代码的评估数据集完全不同
就算修正了上述写法错误,两个结果也不会完全相等,因为评估用的数据集根本不是一个:
- 代码1的交叉验证完全在
X_train/y_train内部完成:10折验证每一轮用90%的训练集拟合模型,在剩下10%没参与当前轮训练的训练集子集上算AUC,你贴出来的10个结果均值约为0.81,反映的是模型在训练集内部拆分验证上的平均表现。 - 代码2是用全量
X_train/y_train拟合模型后,在完全不参与训练的留出测试集X_test/y_test上做评估,测试集数据对模型来说是完全未见的,得分略低于交叉验证均值属于正常现象。
3. 交叉验证本身存在自然波动
你贴出的10折交叉验证结果本身波动范围就不小:单折最高AUC0.91,最低只有0.70,折间差超过0.2,说明数据集样本量偏小、或者不同拆分下的样本类别分布差异较大,单次留出测试集的结果和交叉验证均值存在一定偏差也属于合理范围。
修正predict_proba的写法后重新运行,测试集AUC大概率会回到和交叉验证均值接近的区间,不会再出现0.67的异常低值。如果修正后测试集得分仍然明显偏低,再检查训练集测试集拆分时是否做了分层抽样、是否存在训练测试分布偏移的问题即可。
内容的提问来源于stack exchange,提问作者pyharry
相关产品推荐
相关产品推荐

