XGBoost交叉验证无法识别自定义F1评估函数,如何解决?
自定义F1分数在XGBoost交叉验证中无法运行的解决办法
问题重现
自定义F1评估函数在XGBoost交叉验证时触发错误:Unknown metric function <function f1_eval at 0x7fa0b35ea9d0>,相关代码如下:
自定义F1评估函数
def f1_eval(y_pred, dtrain): y_true = dtrain.get_label() err = 1-f1_score(y_true, np.round(y_pred)) return 'f1_err', err
XGBoost交叉验证代码
if classifier_name in ["gbtree", "gblinear", "dart"]: param['tree_method'] = 'hist' param["eval_metric"] = f1_val#'mlogloss' param['booster'] = classifier_name param['num_class'] = 5 param['n_jobs']=-1 xgb_cv = cv(dtrain=data_dmatrix, params=param, nfold=5, num_boost_round=50, early_stopping_rounds=10,)
错误原因
- 变量名不匹配:定义的函数是
f1_eval,但params["eval_metric"]赋值的是f1_val,名称不一致。 - 传递方式错误:XGBoost的
cv函数不支持在params字典中传入自定义评估函数,必须通过feval参数传递。 - 多分类参数缺失:任务是5分类,但
f1_score默认使用二分类逻辑,未指定average参数,会导致后续计算报错。
修正方案
步骤1:修正自定义评估函数
针对多分类场景补充average参数(可选macro/micro/weighted,根据需求选择):
from sklearn.metrics import f1_score import numpy as np def f1_eval(y_pred, dtrain): y_true = dtrain.get_label() # 以macro平均为例,可根据业务需求调整 err = 1 - f1_score(y_true, np.round(y_pred), average='macro') return 'f1_err', err
步骤2:调整交叉验证代码
移除params中的eval_metric赋值,改用feval参数传递自定义函数:
if classifier_name in ["gbtree", "gblinear", "dart"]: param['tree_method'] = 'hist' param['booster'] = classifier_name param['num_class'] = 5 param['n_jobs'] = -1 xgb_cv = cv( dtrain=data_dmatrix, params=param, nfold=5, num_boost_round=50, early_stopping_rounds=10, feval=f1_eval # 在这里传入自定义评估函数 )
可选:直接返回F1分数(而非1-F1)
如果希望在结果中看到原始F1值,同时适配早停逻辑,需设置maximize=True(因为F1分数越大越好):
def f1_eval(y_pred, dtrain): y_true = dtrain.get_label() score = f1_score(y_true, np.round(y_pred), average='macro') return 'f1', score xgb_cv = cv( dtrain=data_dmatrix, params=param, nfold=5, num_boost_round=50, early_stopping_rounds=10, feval=f1_eval, maximize=True # 告诉XGBoost此指标需要最大化 )
内容的提问来源于stack exchange,提问作者randoamdnbas
相关产品推荐
相关产品推荐

