Catboost.select_features绘图指标与最终模型预测结果不一致是什么原因?
CatBoost特征选择后预测得分远低于特征选择过程得分的原因与解决方案
问题背景
使用CatBoost的select_features接口做特征选择时,特征选择过程中验证集Macro F1最高达到0.6153,训练最终模型后手动用选中的特征预测,得分仅为0.41左右,二者差距极大。
使用的特征选择核心代码如下:
# Parameter grid params = { 'auto_class_weights': 'Balanced', 'boosting_type': 'Ordered', 'thread_count': -1, 'random_seed': 24, 'loss_function': 'MultiClass', 'eval_metric': 'TotalF1:average=Macro', 'verbose': 0, 'classes_count': 3, 'num_boost_round':500, 'early_stopping_rounds': EARLY_STOPPING_ROUNDS } # Datasets train_pool = Pool(train, y_train) test_pool = Pool(test, y_test) # Model Constructor ctb_model = ctb.CatBoostClassifier(**params) # Run feature selection summary = ctb_model.select_features( train_pool, eval_set=test_pool, features_for_select='0-{0}'.format(train.shape[1]-1), num_features_to_select=10, steps=1, algorithm=EFeaturesSelectionAlgorithm.RecursiveByShapValues, shap_calc_type=EShapCalcType.Exact, train_final_model=True, logging_level='Silent', plot=True )
原本的预测代码如下:
from sklearn.metrics import f1_score predictions = ctb_model.predict(test[summary['selected_features_names']], prediction_type='Class') f1_score(y_test, predictions, average='macro')
核心原因
- 最主要原因是预测时错误手动筛选了输入特征:当
train_final_model=True时,select_features返回的ctb_model已经适配了原始输入的全部特征列,推理时会自动忽略未被选中的特征。手动传入仅含选中特征的数据集,相当于给模型传入了维度、顺序和训练时完全不匹配的特征,直接导致预测结果完全失准。 - 次要原因是CatBoost内置
TotalF1和sklearn的f1_score计算逻辑存在微小差异,比如零样本类别处理、类别顺序对齐逻辑,但该差异不会带来0.2左右的得分差,仅为次要影响因素。 - 小概率原因是特征选择过程的绘图展示得分是中间过程的最优得分,最终模型训练时迭代次数不匹配导致得分下降。
解决方案
- 修正预测逻辑,不要手动筛选输入特征,直接传入完整的测试集即可:
predictions = ctb_model.predict(test, prediction_type='Class') f1_score(y_test, predictions, average='macro')
- 优先使用CatBoost内置的评估方法对齐得分口径,调用模型的
score方法传入原始test_pool,得到的结果和特征选择过程的得分口径完全一致:
print(ctb_model.score(test_pool))
- 若需确认特征选择结果,可打印
summary中的best_score字段,和绘图展示的得分做核对,排除绘图展示的误导。
内容的提问来源于stack exchange,提问作者Miguel 2488
相关产品推荐
相关产品推荐

