Sklearn中ROC-AUC结果异常问题及加权ROC-AUC可行性咨询
问题背景
我正在处理一个二分类任务,使用随机森林(设置class_weight="balanced")结合10折分层交叉验证,计算了以下指标:准确率、加权平均精确率、加权平均召回率、加权平均F1值以及ROC-AUC。代码如下:
import pandas as pd import numpy as np from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import StratifiedKFold, cross_validate df = pd.read_csv(input_path+input_file) X = df[features] y = df[["gold_standard"]] clf = RandomForestClassifier(random_state = 42, class_weight="balanced") k_fold = StratifiedKFold(n_splits=10, shuffle=True, random_state=0) scores = cross_validate(clf, X, y, cv=k_fold, scoring = ('accuracy', 'precision_weighted', 'recall_weighted', 'f1_weighted', 'roc_auc')) print("accuracy:", np.mean(scores['test_accuracy'])) print("precision_weighted:", np.mean(scores['test_precision_weighted'])) print("recall_weighted:", np.mean(scores['test_recall_weighted'])) print("f1_weighted:", np.mean(scores['test_f1_weighted'])) print("roc_auc:", np.mean(scores['test_roc_auc']))
针对两种特征设置,得到的结果如下:
- 特征设置1:准确率0.6920,加权精确率0.6888,加权召回率0.6920,加权F1值0.6752,ROC-AUC 0.7120
- 特征设置2:准确率0.6806,加权精确率0.6754,加权召回率0.6806,加权F1值0.6643,ROC-AUC 0.7233
可以看到,特征设置1的前四个指标表现更优,但特征设置2的ROC-AUC反而更高,这与其他指标的趋势相悖,令我困惑。我怀疑这是因为精确率、召回率、F1使用了加权分数,而ROC-AUC未加权导致的。想请教两个问题:
- Sklearn中是否支持二分类的加权ROC-AUC?
- 这种指标趋势相悖的真正原因是什么?
解答
1. Sklearn支持二分类的加权ROC-AUC吗?
答案是肯定的,但默认的roc_auc评分器并没有内置加权逻辑,需要我们通过自定义评分器来实现。
具体来说,你可以使用sklearn.metrics.make_scorer包装roc_auc_score函数,并利用后者的sample_weight参数来指定样本权重。比如如果你想和模型训练时的class_weight="balanced"保持一致的权重策略(即每个类别的样本权重与该类别的样本数量成反比),可以这样实现:
from sklearn.metrics import roc_auc_score, make_scorer import numpy as np def weighted_roc_auc(y_true, y_score): # 计算与class_weight="balanced"对应的样本权重 n_samples = len(y_true) n_classes = len(np.unique(y_true)) class_counts = np.bincount(y_true) sample_weights = n_samples / (n_classes * class_counts) # 按类别映射到每个样本的权重 weights = sample_weights[y_true] return roc_auc_score(y_true, y_score, sample_weight=weights) # 创建自定义评分器,注意需要指定needs_proba=True,因为ROC-AUC需要模型的概率输出 weighted_roc_auc_scorer = make_scorer(weighted_roc_auc, needs_proba=True) # 然后在cross_validate中使用这个评分器 scores = cross_validate( clf, X, y, cv=k_fold, scoring=('accuracy', 'precision_weighted', 'recall_weighted', 'f1_weighted', weighted_roc_auc_scorer) )
这样就能得到考虑类别权重的加权ROC-AUC了。
2. 指标趋势相悖的真正原因
你观察到的现象核心在于:加权精确率/召回率/F1与ROC-AUC衡量的是模型完全不同的能力维度,两者的优化方向本身就可能不一致。
加权类指标(精确率/召回率/F1):这里的
weighted是指按每个类别的样本数量进行加权。也就是说,样本量越大的类别,对最终指标的贡献越高。这类指标关注的是模型在不同类别上的分类准确性,按样本规模加权后的整体表现。如果你的数据集是不平衡的,这类指标会偏向于样本更多的类别——特征1的加权指标更好,说明它在多数类上的预测准确性更高,拉高了整体加权得分。ROC-AUC:这个指标衡量的是模型对正负样本的排序区分能力。它不关注具体的分类阈值,而是看模型能否把正样本的预测概率(或置信度)整体排在负样本前面。ROC-AUC的计算基于真阳性率(TPR)和假阳性率(FPR)的比例,天然不受类别样本数量的影响——哪怕多数类样本很多,它也会平等地关注正负样本的区分质量。特征2的ROC-AUC更高,说明它在“把正样本和负样本区分开”的排序能力上更强,哪怕它在多数类上的分类准确率稍低,但整体的概率排序更合理。
举个具体的例子:假设你的数据集中负类占80%,正类占20%。特征1的模型在负类上的准确率很高(比如90%),但在正类上的准确率很低(比如30%),加权后的整体指标会因为负类的高占比而表现不错;而特征2的模型在负类上的准确率稍低(比如85%),但在正类上的准确率更高(比如50%),虽然整体加权指标稍差,但它能更准确地把正样本的概率排在负样本前面,因此ROC-AUC更高。
这种情况在类别不平衡的数据集上非常常见,完全是正常现象,本质是不同指标的评价侧重点不同。
内容的提问来源于stack exchange,提问作者EmJ

