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

scikit-learn的cross_validate返回NaN评估分数是什么原因?

问题原因

cross_validate返回NaN的核心原因是交叉验证拆分后单折运行报错/指标无法计算,具体对应你代码里的几个问题:

  • 未知类别导致编码环节报错:你使用的OneHotEncoder默认参数为handle_unknown='error',交叉验证拆分训练集、验证集后,如果验证集中的County、Deliveryperiod等onehot编码特征出现了当前训练拆分里不存在的类别,编码环节会直接抛出错误,对应折的评分就会返回NaN。
    你调大折数、重复次数时偶尔能得到有效值,是因为折数越大每折的训练集占比越高,覆盖所有类别的概率更高,拆分是随机的所以无法复现该现象。
  • 分类指标计算时分母为0:如果你的数据集本身样本量较小,欠采样后拆分的某折验证集可能出现某类样本数为0、或是模型预测结果全为同一类的情况,此时precision、f1等指标会因为除数为0返回NaN,scikit-learn默认会返回NaN而不是中断运行。
  • 隐藏问题:数据泄露:你把随机欠采样放在交叉验证流程外部,欠采样用到了所有样本的标签信息,会导致最终评分虚高,虽然这不是返回NaN的直接原因,但属于流程逻辑错误。

修复方案

  1. 修改OneHotEncoder参数,遇到未知类别时不报错,对应位置修改为:
('onehot_cat', OneHotEncoder(handle_unknown='ignore'), onehot_cat),
  1. 给分类指标添加零除法处理,避免指标计算失败返回NaN,先导入依赖,再修改scoring定义:
from sklearn.metrics import make_scorer, f1_score, precision_score, recall_score

scoring = {'acc': 'accuracy',
           'f1': make_scorer(f1_score, zero_division=0),
           'prec': make_scorer(precision_score, zero_division=0),
           'rec': make_scorer(recall_score, zero_division=0)}
  1. 将随机欠采样移动到Pipeline内部,避免数据泄露:
  • 删除最外层的X, y = RandomUnderSampler(random_state=2).fit_resample(X,y)代码
  • 修改full_pipeline定义,加入欠采样步骤:
full_pipeline = Pipeline([
        ('encode',encode_pipeline),
        ('scale', StandardScaler()),
        ('undersample', RandomUnderSampler(random_state=2)),
        ('model', model)
])

内容的提问来源于stack exchange,提问作者J Xkcd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:24:03