如前所述,标准回归方法通常侧重于预测目标变量的条件均值。然而,分位数回归使我们能够对条件分位数(例如中位数、第10百分位数或第90百分位数)进行建模,对预测变量与目标变量分布之间的关系提供了更全面的认识。为了使用梯度提升进行分位数回归,我们需要定义并实施合适的损失函数:即分位数损失,也称作弹珠损失。分位数损失函数针对特定分位数 $\alpha \in (0, 1)$ 的分位数损失函数衡量真实值 $y$ 与预测分位数 $\hat{y}$ 之间的误差。其定义为:$$ L_\alpha(y, \hat{y}) = \begin{cases} \alpha (y - \hat{y}) & \text{如果 } y - \hat{y} > 0 \ (1 - \alpha) (\hat{y} - y) & \text{如果 } y - \hat{y} \le 0 \end{cases} $$这可以使用指示函数 $I(\cdot)$ 更简洁地表示:$$ L_\alpha(y, \hat{y}) = (y - \hat{y}) (\alpha - I(y - \hat{y} < 0)) $$请注意其不对称性:当 $\alpha = 0.5$(中位数)时,损失函数简化为 $0.5 |y - \hat{y}|$,这与平均绝对误差 (MAE) 成比例。低估($\hat{y} < y$)的惩罚等于高估($\hat{y} > y$)的惩罚。当 $\alpha > 0.5$ 时,损失函数对低估($y > \hat{y}$)的惩罚比高估更重。这促使模型预测更高的值,对应于上分位数。当 $\alpha < 0.5$ 时,损失函数对高估($y < \hat{y}$)的惩罚更重,将预测推向更低的分位数。下图展示了不同 $\alpha$ 值下的弹珠损失。{"layout": {"xaxis": {"title": "预测误差 (y - y_hat)"}, "yaxis": {"title": "分位数损失"}, "title": "不同Alpha值下的弹珠(分位数)损失函数", "legend": {"title": "Alpha"}}, "data": [{"x": [-10, -5, 0, 5, 10], "y": [1, 0.5, 0, 4.5, 9], "type": "scatter", "mode": "lines", "name": "0.9", "line": {"color": "#fa5252"}}, {"x": [-10, -5, 0, 5, 10], "y": [5, 2.5, 0, 2.5, 5], "type": "scatter", "mode": "lines", "name": "0.5 (中位数)", "line": {"color": "#4c6ef5"}}, {"x": [-10, -5, 0, 5, 10], "y": [9, 4.5, 0, 0.5, 1], "type": "scatter", "mode": "lines", "name": "0.1", "line": {"color": "#40c057"}}]}该图显示了分位数损失特有的“弹珠”形状。请注意斜率在零误差处如何变化,以及不对称性如何取决于分位数 $\alpha$。对于 $\alpha=0.9$,正误差(低估)受到更重的惩罚,而对于 $\alpha=0.1$,负误差(高估)则受到更大的惩罚。$\alpha=0.5$ 对正负误差对称处理。提升算法中的梯度与Hessian梯度提升算法通过迭代地将基础学习器(通常是树)拟合到损失函数相对于当前预测的负梯度。因此,我们需要 $L_\alpha(y, \hat{y})$ 相对于 $\hat{y}$ 的一阶导数(梯度)。XGBoost 和 LightGBM 等一些高级实现也使用二阶导数(Hessian)来实现更快的收敛和正则化。让我们找出梯度:$$ g = \frac{\partial L_\alpha(y, \hat{y})}{\partial \hat{y}} = I(y - \hat{y} < 0) - \alpha = I(\hat{y} > y) - \alpha $$因此,梯度为:$-\alpha$,如果 $\hat{y} \le y$(低估或正确预测)$1 - \alpha$,如果 $\hat{y} > y$(高估)现在,考虑 Hessian:$$ h = \frac{\partial^2 L_\alpha(y, \hat{y})}{\partial \hat{y}^2} = \frac{\partial g}{\partial \hat{y}} $$梯度是一个阶跃函数,这意味着它的导数在除 $\hat{y} = y$ 点之外的所有地方都为零,而在 $\hat{y} = y$ 点处,导数是未定义的(数学上,它涉及一个狄拉克δ函数)。标准的梯度提升实现,特别是那些使用二阶近似(如 XGBoost)的实现,需要一个明确定义的 Hessian。我们如何处理这个问题?内置目标函数: 像 LightGBM 这样的库通常对分位数回归有内置支持(objective='quantile')。在这种情况下,库在内部处理 Hessian,可能使用近似值或适用于非平滑目标函数的特定算法。如果可用,使用内置目标函数通常是推荐的方法。自定义目标函数 - 近似 Hessian: 当定义自定义目标函数时,您必须为每个数据点返回梯度和 Hessian 值。由于真实的 Hessian 存在问题,常见的做法是为 Hessian 返回一个小的正常量(例如 1,或更小的值如 1e-6)。这提供了数值稳定性,并允许算法(通常使用 $g/h$ 或类似项)继续执行。虽然它并非严格意义上的真实二阶导数,但在实践中通常效果良好。自定义目标函数 - 零 Hessian: 一些框架可能允许或隐式处理零 Hessian,从而有效地回退到那些步骤的一阶梯度方法。然而,在期望二阶信息的库中,明确提供一个小的正值通常更有效。实现自定义分位数目标函数让我们看看如何在 Python 中为 XGBoost 或 LightGBM 等库构建自定义分位数损失函数。这些库期望一个函数,该函数接收当前预测值 (preds) 和真实标签 (dtrain,其中包含 y),并为每个样本返回梯度和 Hessian。以下是自定义分位数目标函数的 Python 函数结构:import numpy as np def quantile_objective(alpha): """ 分位数回归的自定义目标函数。 参数: alpha (浮点数): 目标分位数,必须在 (0, 1) 之间。 返回值: 可调用对象:一个与 XGBoost/LightGBM 自定义目标函数兼容的函数。 """ def objective_function(preds, dtrain): """ 计算分位数损失的梯度和 Hessian。 参数: preds (np.ndarray): 当前模型预测。 dtrain: 数据容器(例如 xgboost.DMatrix 或 lightgbm.Dataset) 通过 dtrain.get_label() 获取真实标签。 返回值: grad (np.ndarray): 损失函数相对于 preds 的梯度。 hess (np.ndarray): 损失函数相对于 preds 的 Hessian。 """ labels = dtrain.get_label() errors = preds - labels # 注意:使用 preds - labels 与 I(preds > y) 约定一致 # 计算梯度 grad = np.where(errors > 0, 1 - alpha, -alpha) # 计算 Hessian(使用小的常数近似) # 一个小的正常量有助于确保算法的稳定性。 # 具体值可能需要调整或实验。 hess = np.full_like(preds, 1.0) # 或者更小的值,如 1e-6 return grad, hess return objective_function # 示例用法 # alpha_value = 0.75 # 目标是第75百分位数 # custom_obj = quantile_objective(alpha_value) # 在 XGBoost 中: # model = xgb.train(params, dtrain, num_boost_round=100, obj=custom_obj) # 在 LightGBM 中: # model = lgb.train(params, dtrain, num_boost_round=100, fobj=custom_obj)重要考量:库支持: 务必查阅所选库(XGBoost、LightGBM、CatBoost)的文档。它们可能提供内置的分位数回归目标函数(例如 LightGBM 中带有 alpha 参数的 objective='quantile'),这些函数通常经过优化,比自定义实现更受青睐。CatBoost 也支持分位数损失函数。Hessian 近似: 在自定义目标函数中选择 Hessian 的常数值有时会影响收敛速度和稳定性。如果使用自定义实现,您可以尝试不同的小的正值(例如 1.0, 0.1, 1e-3, 1e-6)。调整 $\alpha$: 如果您根据领域知识或问题要求尝试建模特定分位数,分位数级别 $\alpha$ 被视为一个超参数。如果需要建模多个分位数,通常会为每个所需 $\alpha$ 训练单独的模型。评估指标: 在训练分位数回归模型时,像 RMSE(侧重于均值)这样的标准指标不适合用于评估。请使用与分位数相关的指标,例如在验证集上的分位数损失本身,或者在预测区间时使用 Winkler 分数等指标。您可能还需要实现自定义评估指标(在第 7 章中介绍)。通过实施或使用分位数损失函数,您可以使梯度提升模型具备超越均值预测、估计条件分位数的能力,从而为各种特殊任务提供对底层数据分布更丰富、更全面的认识。