GridSearchCV自定义评分函数问题:预测值全0及make_scorer报错
GridSearchCV结合LightGBM自定义评分函数问题解析与修复
问题1:直接使用自定义评分函数时y_pred全为0
现象与代码问题
用户直接将自定义函数summary_of_threshold作为scoring参数传入GridSearchCV,结果模型输出的y_pred全为0。
核心原因
- 错误依赖全局测试集:函数中直接调用全局的
X_test,而非GridSearchCV交叉验证过程中自动传入的当前折验证集X。GridSearchCV的评分函数会使用CV划分后的验证数据,而非用户定义的全局测试集,这种误用会导致模型在陌生数据上出现异常预测。 - 误用硬分类结果:要计算目标假阳性率对应的阈值,需要模型输出的正类概率,而非
predict()返回的0/1硬分类结果。硬分类结果无法调整阈值,自然无法找到对应目标FPR的临界值。 - Early Stopping适配问题:GridSearchCV每次CV训练都会重新初始化模型,传入全局
X_val作为eval_set会导致所有折共用同一验证集,违背交叉验证的逻辑,也可能干扰模型训练效果。
问题2:使用make_scorer触发参数缺失报错
报错信息
TypeError: summary_of_threshold() missing 1 required positional argument: 'y'
核心原因
make_scorer默认要求评分函数的签名为(y_true, y_pred),但用户定义的函数是(estimator,X,y)格式(该格式是直接传入GridSearchCVscoring参数的要求)。两种模式的参数传递逻辑不兼容,导致参数缺失报错。
修复方案
方案1:正确实现直接传入GridSearchCV的自定义评分函数
调整函数逻辑,使用CV传入的验证集数据,改用概率输出计算阈值:
def summary_of_threshold(estimator, X, y): fpr_target = 0.0006 # 获取正类概率,用于阈值计算 y_pred_proba = estimator.predict_proba(X)[:, 1] # 使用当前折的真实标签y,而非全局测试集标签 threshold, fpr = find_threshold(y, y_pred_proba, fpr_target) print(f"当前折FPR: {fpr}, 对应阈值: {threshold}") # 返回需要优化的指标:最小化FPR与目标值的差值 return abs(fpr - fpr_target) # 初始化GridSearchCV,直接传入自定义评分函数 gsearch = GridSearchCV(gbm_model, param_grid=grid_parametaers, scoring=summary_of_threshold, cv=3, n_jobs=1) gsearch.fit( X=X_train, y=y_train.label, categorical_feature=categorical_features, verbose=10, callbacks=[early_stopping(early_stopping_rounds)] )
方案2:正确使用make_scorer创建自定义评分器
调整函数为make_scorer要求的签名格式,同时指定需要概率输出:
# 定义基于真实标签和概率的评分函数 def score_by_fpr_target(y_true, y_score): fpr_target = 0.0006 threshold, fpr = find_threshold(y_true, y_score, fpr_target) # 返回需要优化的指标:最小化FPR与目标值的差值 return abs(fpr - fpr_target) # 创建自定义评分器,指定需要概率输出,且指标越小越好 customized_scorer = make_scorer(score_by_fpr_target, greater_is_better=False, needs_proba=True) gsearch = GridSearchCV(gbm_model, param_grid=grid_parametaers, scoring=customized_scorer, cv=3, n_jobs=1) gsearch.fit( X=X_train, y=y_train.label, categorical_feature=categorical_features, verbose=10, callbacks=[early_stopping(early_stopping_rounds)] )
额外注意事项
find_threshold函数校验:确保该函数能通过ROC曲线的FPR和阈值序列,插值找到最接近目标FPR的临界值,这是整个逻辑的核心。- 规避全局变量:评分函数中禁止使用全局测试集/验证集,必须依赖GridSearchCV传入的当前折数据,保证交叉验证的客观性。
- Early Stopping逻辑:GridSearchCV会自动为每个CV折划分训练/验证数据,无需传入外部
eval_set,否则会破坏交叉验证的独立性。
内容的提问来源于stack exchange,提问作者Bourne813
相关产品推荐
相关产品推荐

