针对欠拟合CatBoostRegressor模型的调优方案(固定训练集)
问题解答
1. CatBoostRegressor默认参数是否随数据集动态变化?
默认参数不会随数据集动态变化,所有基础核心参数(如learning_rate=0.03、depth=6、l2_leaf_reg=3等)都是固定值。仅少数明确标注“自动适配”的参数(如auto_class_weights)会根据数据调整,其余均为静态默认配置。
2. MAE的权重w_i及“对象/组权重”的含义
- 默认状态下,所有样本的权重
w_i=1,MAE即为所有样本绝对误差的算术平均值。 - “使用对象/组权重计算指标”指:若通过
sample_weight为单个样本分配权重(比如高价值样本权重设为2),或通过group_id指定分组并启用组权重,MAE会计算加权平均绝对误差,公式为:MAE = (Σw_i * |y_i - ŷ_i|) / Σw_i。 - 权重均等本身无法直接解决欠拟合问题,欠拟合主要源于模型容量不足或特征信息缺失,权重仅用于调整不同样本对损失的贡献程度。
3. 欠拟合场景下learning rate和树数量的调优建议
欠拟合说明模型容量不足以捕捉数据中的复杂模式,可按以下方向调优:
- 优先调整树深度:将默认
depth=6提升至8-12(当前为欠拟合,无需过度担心过拟合),直接提升模型的拟合能力。 - learning rate与迭代次数配合:
- 若需快速训练:将
learning_rate从默认0.03提高至0.05-0.1,同时将迭代次数增至1000-1500,高学习率让每棵树的贡献更显著,快速提升拟合效果。 - 若允许稍长训练时间:将
learning_rate降至0.01-0.02,迭代次数增至2000-5000,小学习率配合多棵树能更精细地拟合数据规律。
- 若需快速训练:将
- 辅助调优参数:
- 降低
l2_leaf_reg(默认3)至1-2,削弱正则化强度,让模型更自由地拟合数据。 - 开启
grow_policy='Lossguide',让树根据损失值优先分裂高误差样本,比默认的Depthwise模式更聚焦关键拟合点。
- 降低
4. 自定义loss_function和eval_metric的具体实例
自定义加权MAE损失函数
实现对高误差样本加倍权重的MAE损失,需同时提供损失计算、梯度、海森矩阵三个函数(CatBoost基于梯度提升,依赖导数信息):
import numpy as np from catboost import CatBoostRegressor # 自定义损失计算 def custom_weighted_mae(y_true, y_pred): error = np.abs(y_true - y_pred) # 对误差超过100的样本设置2倍权重 weights = np.where(error > 100, 2.0, 1.0) return np.mean(weights * error) # 梯度计算 def custom_mae_grad(y_true, y_pred): error = y_true - y_pred weights = np.where(np.abs(error) > 100, 2.0, 1.0) grad = -np.sign(error) * weights return grad # 海森矩阵计算(MAE的海森矩阵为0,用极小值替代避免报错) def custom_mae_hess(y_true, y_pred): error = y_true - y_pred weights = np.where(np.abs(error) > 100, 2.0, 1.0) hess = np.full_like(error, 1e-3) * weights return hess # 模型中使用自定义损失 model = CatBoostRegressor( iterations=1000, random_seed=123, cat_features=['month_number', 'day_of_week', 'year'], loss_function=(custom_weighted_mae, custom_mae_grad, custom_mae_hess), eval_metric='MAE', learning_rate=0.05 )
自定义加权MAPE评估指标
仅需实现指标计算函数即可,无需梯度和海森矩阵:
import numpy as np from catboost import CatBoostRegressor def custom_weighted_mape(y_true, y_pred): # 避免除以0,给真实值加极小偏移 y_true_safe = np.where(y_true == 0, 1e-6, y_true) # 对真实值大于1000的样本设置1.5倍权重 weights = np.where(y_true > 1000, 1.5, 1.0) mape = np.mean(weights * np.abs((y_true - y_pred)/y_true_safe)) * 100 return mape # 模型中使用自定义评估指标 model = CatBoostRegressor( iterations=1000, random_seed=123, cat_features=['month_number', 'day_of_week', 'year'], loss_function='MAE', eval_metric=custom_weighted_mape, learning_rate=0.05 )
内容的提问来源于stack exchange,提问作者user177196
相关产品推荐
相关产品推荐

