使用CatBoost的get_best_score方法时遇到"KeyError: 'learn'"错误如何解决?

问题现象与背景

当开发者使用CatBoost这一强大的梯度提升库时,get_best_score方法常被用于获取模型训练过程中的最佳评估指标值。然而许多用户在调用model.get_best_score()时会意外遭遇"KeyError: 'learn'"错误,这通常发生在以下场景:

  • 使用自定义评估指标(metric)时
  • 未正确设置验证数据集
  • 模型训练未完成提前中断

根本原因分析

该错误的本质是CatBoost内部数据结构缺失必要字段。通过分析源码发现,get_best_score方法默认尝试访问best_score_['learn']字典值,但以下情况会导致该字段不存在:

  1. 验证集未配置:当仅提供训练数据未设置eval_set时
  2. 评估指标冲突:自定义指标与内置指标名称重复
  3. 训练中断:early_stopping触发时未完整记录指标
  4. 版本兼容性问题:CatBoost 0.26前后版本API差异

5种解决方案

方案1:显式指定验证集

model.fit(
    X_train, y_train,
    eval_set=(X_val, y_val),  # 必须提供验证集
    verbose=100
)
print(model.get_best_score())

方案2:检查指标名称

确保自定义指标不与内置指标(Accuracy, AUC, RMSE等)重名:

class CustomMetric:
    def get_final_error(self, error, weight):
        return error
    
    def is_max_optimal(self):
        return True
        
    def evaluate(self, approxes, target, weight):
        # 实现自定义逻辑
        return (0.5, 1)

方案3:使用安全访问方式

best_score = model.get_best_score()
learn_score = best_score.get('learn', 'N/A')  # 字典安全访问
test_score = best_score.get('test', 'N/A')

方案4:升级CatBoost版本

较新版本(≥1.0)优化了错误处理:

pip install --upgrade catboost

方案5:完整训练流程验证

使用官方示例验证基础功能:

from catboost import CatBoostClassifier
model = CatBoostClassifier(iterations=100)
model.fit(X, y, eval_set=(X_val, y_val), plot=True)
assert 'learn' in model.get_best_score()

深度技术解析

CatBoost在内部通过BestScoreTracker类管理指标数据,其核心逻辑包括:

组件功能
MetricHolder存储各阶段指标值
EarlyStopping监控验证集表现
SnapshotManager定期保存检查点

当出现"learn"键缺失时,实际上反映了MetricHolder初始化不完整的问题。通过设置logging_level='Debug'可查看详细日志:

model.fit(..., logging_level='Debug')