You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cross_val_score评估不平衡数据集时Brier Skill Score返回NaN的问题排查与解决

cross_val_score评估不平衡数据集时Brier Skill Score返回NaN的问题排查与解决

看起来你在处理高度不平衡的欺诈检测数据集时,遇到了所有模型(包括基线)的Brier Skill Score(BSS)在交叉验证中全返回NaN的问题,我帮你一步步排查原因并给出解决办法:

一、最可能的核心问题:概率数组维度不匹配

在二分类任务中,sklearn模型的predict_proba()方法默认返回二维数组(形状为(n_samples, 2)),其中第一列是负类概率,第二列是正类概率。你的brier_skill_score函数直接将这个二维数组传入brier_score_loss,虽然sklearn会尝试自动处理,但在某些边缘场景(比如某fold中测试集只有单一类别)可能会引发计算异常,最终导致NaN。

解决方法是显式提取正类的概率(一维数组)传入brier_score_loss,修改你的brier_skill_score函数:

def brier_skill_score(y_true, y_prob):
    """ Compute the Brier Skill Score (BSS).
    - 0.0 = no skill (same as baseline)
    - >0.0 = better than baseline
    - <0.0 = worse than baseline
    """
    # 处理二维概率数组,提取正类概率(假设y_true中1是正类)
    if y_prob.ndim == 2:
        y_prob = y_prob[:, 1]
    
    pos_prob = np.count_nonzero(y_true) / len(y_true)
    ref_probs = [pos_prob for _ in range(len(y_true))]  # baseline (predict always prior prob)
    bs_ref = brier_score_loss(y_true, ref_probs)
    bs_model = brier_score_loss(y_true, y_prob)
    
    if bs_ref == 0:  # 避免除以0(测试集只有单一类别时)
        return 0.0
    
    return 1.0 - (bs_model / bs_ref)

二、次要排查点:分层交叉验证的边缘情况

你的数据集很小(仅2133行,66个正例),使用RepeatedStratifiedKFold时,有可能出现某一个fold的测试集中只有单一类别(全0或全1)。虽然你的代码已经处理了bs_ref == 0的情况,但可以额外添加日志排查:

在brier_skill_score函数中临时加入打印语句,查看每个fold的测试集分布和计算值:

from collections import Counter

def brier_skill_score(y_true, y_prob):
    # 临时添加:打印当前fold测试集分布
    print(f"当前fold测试集分布: {Counter(y_true)}")
    
    # 处理二维概率数组
    if y_prob.ndim == 2:
        y_prob = y_prob[:, 1]
    
    pos_prob = np.count_nonzero(y_true) / len(y_true)
    ref_probs = [pos_prob for _ in range(len(y_true))]
    bs_ref = brier_score_loss(y_true, ref_probs)
    bs_model = brier_score_loss(y_true, y_prob)
    
    print(f"bs_ref: {bs_ref}, bs_model: {bs_model}")
    
    if bs_ref == 0:
        print("测试集只有单一类别,返回BSS=0.0")
        return 0.0
    
    bss = 1.0 - (bs_model / bs_ref)
    print(f"当前fold BSS: {bss}")
    return bss

运行后如果看到某fold的测试集只有单一类别,这是数据集过小导致的正常现象,不会影响整体结果(因为其他fold会返回有效数值);如果所有fold都出现这种情况,建议调整交叉验证参数(比如减小n_splits)。

三、其他潜在问题排查

  1. ImbPipeline的使用:你使用了imblearn.pipeline.Pipeline,如果没有添加任何采样器(如SMOTE),其实和sklearn的普通Pipeline功能一致,不会引发问题;如果后续要添加采样器,建议将采样器放在预处理步骤之后、模型之前。
  2. 模型的概率输出有效性:确保所有模型的predict_proba返回的概率值都在[0,1]区间内,没有NaN值(sklearn模型默认不会输出NaN,除非数据有缺失且未处理,但你的预处理已经包含了Imputer,所以这一点大概率没问题)。

验证修改效果

修改后重新运行代码,基线模型的BSS应该接近0.0(因为基线模型和参考基准的性能一致),而其他模型(如逻辑回归、随机森林)应该返回有效BSS值(大于0表示比基线好)。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 08:10:43