自定义Sklearn评分器:计算Top x%预测结果的ROC AUC
解决Top x%样本的ROC AUC/平均精度计算问题
现有代码的问题分析
你的代码存在两个核心问题:
- 拼写错误:
len(predicitons_df)中的变量名拼错,应为predictions_df,这会导致k值计算错误(比如比例设为1时,k不等于全部样本数量,所以结果和常规ROC AUC不同)。 - 逻辑偏差:直接截取Top k样本后调用
roc_auc_score,本质是计算这k个样本内部的ROC AUC,而非你需要的「全局排序下Top x%高置信度样本的模型区分能力」。如果Top k样本中类别单一(比如全是正/负样本),函数会始终返回0.5或1.0,这就是你看到“始终返回相同值”的原因。
正确实现方案
Top x% Partial ROC AUC
这个函数基于全局样本的预测概率排序,计算ROC曲线中对应Top x%高置信度样本部分的AUC,精准反映模型在高价值预测区间的性能:
import pandas as pd from sklearn.metrics import roc_curve def top_x_roc_auc(y_true, y_score, top_pct=0.25): # 按预测得分降序排序所有样本 sorted_indices = y_score.argsort()[::-1] y_true_sorted = y_true[sorted_indices] y_score_sorted = y_score[sorted_indices] n_total = len(y_true) k = round(n_total * top_pct) if k == 0: raise ValueError("Top占比过小,未筛选到有效样本") # 确定Top k样本的阈值(第k个样本的预测得分) threshold_k = y_score_sorted[k-1] if k < n_total else y_score_sorted[-1] # 计算全局ROC曲线,并筛选出阈值>=threshold_k的部分(对应Top k样本) fpr, tpr, thresholds = roc_curve(y_true, y_score, pos_label=1) mask = thresholds >= threshold_k # 补充原点(0,0),确保曲线完整 fpr_partial = [0.0] + list(fpr[mask]) tpr_partial = [0.0] + list(tpr[mask]) # 用梯形法计算Partial AUC auc_partial = 0.0 for i in range(1, len(fpr_partial)): auc_partial += (fpr_partial[i] - fpr_partial[i-1]) * (tpr_partial[i] + tpr_partial[i-1]) / 2 return auc_partial
Top x% 平均精度(AP)
同理,针对平均精度的Top x%计算,聚焦高置信度样本的查准率-召回率表现:
from sklearn.metrics import precision_recall_curve def top_x_average_precision(y_true, y_score, top_pct=0.25): sorted_indices = y_score.argsort()[::-1] y_true_sorted = y_true[sorted_indices] n_total = len(y_true) k = round(n_total * top_pct) if k == 0: raise ValueError("Top占比过小,未筛选到有效样本") # 截取Top k样本 y_true_top = y_true_sorted[:k] y_score_top = y_score_sorted[:k] # 计算前k个样本的查准率-召回率曲线 precision, recall, _ = precision_recall_curve(y_true_top, y_score_top) # 用梯形法计算平均精度 ap = 0.0 for i in range(1, len(recall)): ap += (recall[i-1] - recall[i]) * precision[i] return ap
验证说明
- 当
top_pct=1.0时,top_x_roc_auc的结果会和sklearn.metrics.roc_auc_score完全一致,符合预期。 - 若Top x%样本中同时存在正负样本,函数会返回合理的区分度指标;若类别单一,会返回0.5(ROC AUC)或对应类别的精度值(平均精度)。
内容的提问来源于stack exchange,提问作者Kyle Mouly
相关产品推荐
相关产品推荐

