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

基于GPU与Optuna的CatBoost分类器自定义指标报错排查

解决CatBoost自定义指标的格式错误问题

错误根源

你触发的Invalid metric description错误,核心原因是自定义指标的传入方式完全错误:

  • CatBoost的custom_metric参数仅用于给内置指标传递自定义参数(比如Precision:class_id=1),不能用来指定自定义函数
  • 真正传入自定义评估函数,需要使用eval_metric参数,且直接传入函数对象,而非字符串格式

修复步骤及完整代码

1. 修正自定义指标的传入方式

将CatBoostClassifier初始化时的custom_metric='Precision:custom_precision'替换为eval_metric=custom_precision

2. 适配多分类任务的自定义函数签名

CatBoost对多分类任务的自定义指标函数,会传入以下参数:

  • y_true: 一维数组,存储样本的真实类别标签
  • y_pred: 二维数组(形状[样本数, 类别数]),存储每个样本属于各类别的概率
    你之前的函数错误地将y_true当成了二维数组,需要调整逻辑。

3. 补充Optuna目标函数的返回值

原代码最后没有返回score,Optuna的目标函数必须返回优化目标值,否则无法完成超参数搜索。

修改后的完整目标函数代码:

def objective(trial, data=data):
    num_train_pool = data["num_train_pool"]
    num_test_pool = data["num_test_pool"]
    true_labels_test = data["true_labels_test"]
    
    params = {
        'objective': 'MultiClass',
        'task_type': 'GPU',
        'logging_level': 'Verbose',
        'bootstrap_type': 'Bayesian',
        'learning_rate': trial.suggest_loguniform('learning_rate', 1e-4, 1),
        'depth': trial.suggest_int('depth', 3, 12),
        'l2_leaf_reg': trial.suggest_loguniform('l2_leaf_reg', 1e-2, 1),
        'border_count': trial.suggest_int('border_count', 32, 255)
    }

    def custom_precision(y_true, y_pred):
        # 获取每个样本的预测类别(概率最大的类别)
        pred_labels = y_pred.argmax(axis=1)
        
        # 计算-1类的真阳性和假阳性
        tp_neg1 = ((y_true == -1) & (pred_labels == -1)).sum()
        fp_neg1 = ((y_true != -1) & (pred_labels == -1)).sum()
        
        # 计算1类的真阳性和假阳性
        tp_pos1 = ((y_true == 1) & (pred_labels == 1)).sum()
        fp_pos1 = ((y_true != 1) & (pred_labels == 1)).sum()
        
        total_tp = tp_neg1 + tp_pos1
        total_fp = fp_neg1 + fp_pos1
        
        return total_tp / (total_tp + total_fp + 1e-8)
    
    # 修正自定义指标的传入方式
    model = catboost.CatBoostClassifier(**params, eval_metric=custom_precision, random_seed=65)
    model.fit(
        num_train_pool, 
        verbose=0, 
        eval_set=num_test_pool,
        early_stopping_rounds=5
    )

    preds = model.predict(num_test_pool)
    score = custom_precision(true_labels_test, model.predict_proba(num_test_pool))
    
    # 必须返回优化目标值给Optuna
    return score

额外注意事项

  • 你已经通过Pool传入了类别权重,训练时模型会自动应用这些权重,无需在自定义指标中重复处理
  • 如果需要基于自定义指标做早停,确保eval_metric指定的是该函数,CatBoost会自动用它来判断早停条件
  • 多分类任务中,model.predict()返回的是直接的类别标签,而自定义指标在fit过程中接收的y_pred是概率矩阵,因此在计算最终score时,需要传入predict_proba的结果以保持逻辑一致

内容的提问来源于stack exchange,提问作者Luis Miguel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:17:14