【学习笔记】LGBM
LightGBM(LGBM)回归学习笔记
这份笔记以 LightGBM 用于回归(regression) 为主线,重点整理三部分:
- LGBM 的 boosting 过程
- LGBM 损失函数的设计过程(泰勒展开)
- LGBM 叶子输出与分裂增益的推导
同时,每个部分都会结合它在
lightgbm库中对应的重要参数来理解。
0. 先建立整体认知:LGBM 在做什么?
LightGBM 本质上是 梯度提升决策树(GBDT) 的高效实现。用于回归时,它不是一次训练出一棵很大的树,而是:
- 先给所有样本一个初始预测;
- 然后按轮次不断训练新树;
- 每一棵新树都只负责修正当前模型还没学好的部分;
- 最终模型是很多棵树的加和。
整体形式可以写成:
其中:
- \(\hat y_i^{(t)}\):第 \(t\) 轮后的预测值
- \(f_t(x_i)\):第 \(t\) 棵树对样本 \(x_i\) 的输出
- \(\eta\):学习率(learning rate)
对应的核心参数包括:
boosting_type:提升方式,常用gbdtobjective:任务目标,回归常用regression、regression_l1、huber等learning_rate:每棵树对最终预测的修正步长n_estimators/num_iterations:总 boosting 轮数,也就是树的数量early_stopping_round:验证集上若若干轮没有提升,则提前停止
1. LGBM 的 boosting 过程
1.1 数据准备与训练目标
训练开始前,需要准备:
- 特征矩阵 \(X\)
- 回归标签 \(y\)
- 训练集 / 验证集划分
如果存在类别特征、缺失值、异常值等,也需要在训练前处理好。LightGBM 对缺失值和类别特征有一定原生支持,但建模前仍应明确数据语义。
与这一步最相关的参数有:
categorical_feature:指定类别特征objective:指定优化目标metric:验证指标,如l2、rmse、l1、mae
1.2 初始化模型
Boosting 不是从空白开始,而是先给出一个常数预测。对回归任务,常见做法是用标签均值或某个更合适的常数作为初始值。
记初始预测为:
此时模型还没有树,后续每一轮新树都是在当前预测的基础上继续修正。
这一步通常由框架内部完成,用户一般不会手动指定初始常数,但要理解后续所有梯度都是基于“当前预测”来算的。
1.3 第 t 轮:先看当前模型还有哪些误差
假设在第 \(t-1\) 轮后,样本 \(i\) 的预测值是:
真实值是:
本轮的目标不是重新拟合原始标签,而是让当前总损失继续下降。
如果使用一般形式的损失函数,则整体目标写成:
对于平方误差回归,单样本损失为:
与这一步最相关的参数:
objective='regression':对应平方误差类目标objective='regression_l1':对应绝对误差类目标metric='rmse'、metric='l2'、metric='mae':只影响评估,不直接改变训练目标,除非与objective一起统一设置
1.4 计算一阶梯度和二阶梯度
LightGBM 在第 \(t\) 轮不会直接拿原始标签去训练树,而是对当前损失函数在当前预测点求导,得到每个样本的:
- 一阶梯度:表示当前应该往哪个方向修正
- 二阶梯度:表示局部曲率,帮助决定修正幅度
定义为:
对于平方误差:
有:
所以在平方损失下,可以把 boosting 粗略理解为:每一轮都在拟合当前残差(更准确地说,是拟合负梯度方向)。
与这一步最相关的参数:
objective:决定梯度和 Hessian 的具体形式boosting_type='gbdt':决定采用梯度提升框架
1.5 用梯度信息训练一棵新树
第 \(t\) 轮要学习一个新函数:
它本质上是一棵回归树。加入这棵树后,模型变为:
如果再考虑学习率:
LightGBM 训练这棵树时,不再直接最小化原始目标,而是最小化其二阶近似形式。新树要做的事情可以理解为:
- 把“梯度相似”的样本分到同一叶子里;
- 每个叶子输出一个统一修正量;
- 让这棵树加入后目标函数下降最多。
与树结构最相关的参数:
num_leaves:最多叶子数,直接决定树复杂度上限max_depth:树深度限制,避免 leaf-wise 生长过深min_data_in_leaf/min_child_samples:每个叶子的最少样本数min_sum_hessian_in_leaf/min_child_weight:每个叶子的最小 Hessian 和min_gain_to_split:分裂所需最小增益
1.6 LightGBM 如何长树:leaf-wise + histogram
这是 LightGBM 和传统 level-wise GBDT 的一个重要区别。
(1)leaf-wise 生长
LightGBM 采用 leaf-wise(叶子优先) 的策略:
- 不是每一层同时扩展;
- 而是在当前所有叶子中,优先选择“增益最大”的那个叶子继续分裂。
优点是:在相同树规模下,通常更容易降低损失。
缺点是:如果不加限制,更容易过拟合。
所以在实际训练中,常需要配合:
num_leavesmax_depthmin_data_in_leafmin_gain_to_split
一起控制复杂度。
(2)histogram 加速找分裂点
LightGBM 不会对连续特征的所有取值逐一尝试切分,而是先把特征值离散到若干个桶(bin)里,再在桶边界上找最优切分点。
这使得训练速度更快、内存占用更低。
对应参数:
max_bin:每个特征最多分多少个桶min_data_in_bin:每个 bin 最少样本数feature_fraction:每轮建树时随机采样部分特征bagging_fraction、bagging_freq:样本采样相关参数
1.7 用学习率更新整体预测
当第 \(t\) 棵树训练好后,对每个样本都会落到该树的某个叶子,得到叶子输出值。然后整体预测更新为:
这里 learning_rate 很关键:
- 较小的
learning_rate:单棵树步子更小,通常更稳,但需要更多树 - 较大的
learning_rate:收敛更快,但更容易过拟合或震荡
因此 learning_rate 与 n_estimators / num_iterations 往往需要配合调节。
1.8 验证、早停与最终预测
训练过程中,通常会在验证集上监控指标,如:
rmsel2maer2(通常需外部自行计算)
如果验证集指标连续若干轮没有提升,可以 early stopping,确定最佳迭代轮数。
对应参数:
metricearly_stopping_roundn_estimators/num_iterations
最终模型是多棵树的加和,对新样本推理时:
- 依次让样本通过每一棵树;
- 落到对应叶子;
- 取叶子值求和;
- 再乘上学习率累积,得到最终回归预测。
2. LGBM 损失函数的设计过程(泰勒展开)
这一部分是理解 LightGBM / XGBoost 的核心。
2.1 第 t 轮的原始目标函数
在 boosting 第 \(t\) 轮,模型预测更新为:
此时整体目标函数写为:
其中:
- \(l(\cdot)\):单样本损失函数
- \(\Omega(f_t)\):第 \(t\) 棵树的复杂度正则项
常见树复杂度项写成:
其中:
- \(T\):叶子数
- \(w_j\):第 \(j\) 个叶子的输出值
- \(\gamma\):每增加一次分裂 / 叶子复杂度代价
- \(\lambda\):叶子权重的 \(L_2\) 正则项
和这些量对应的重要参数:
objective:定义损失函数 \(l(\cdot)\)lambda_l2/reg_lambda:对应叶子输出的 \(L_2\) 正则lambda_l1/reg_alpha:LightGBM 也支持 \(L_1\) 正则,但下面推导主线以 \(L_2\) 为主min_gain_to_split:对应复杂度门槛,和推导中的 \(\gamma\) 思想一致num_leaves:控制 \(T\) 的上限
2.2 为什么不能直接优化这个目标?
困难在于:
里面的 \(f_t(x_i)\) 是未知函数,而且它本身还是一棵树,意味着同时要优化:
- 树的结构
- 每个叶子的输出值
这个问题直接做非常复杂。
所以 GBDT / XGBoost / LightGBM 的经典做法是:
在当前预测点附近,对损失函数做二阶泰勒展开,把复杂目标近似成一个更容易优化的二次形式。
2.3 二阶泰勒展开
对单样本损失项:
在当前预测点 \(\hat y_i^{(t-1)}\) 附近展开:
其中:
这说明每个样本最终只需要提供两个统计量:
- 一阶梯度 \(g_i\)
- 二阶梯度 \(h_i\)
与这一步最强相关的参数依然是:
objective
因为不同 objective 会决定 \(g_i\) 和 \(h_i\) 的具体表达式。
2.4 代回总目标函数
将二阶展开代回总目标:
注意其中:
与当前要学习的树 \(f_t\) 无关,因此在优化 \(f_t\) 时可以视为常数项去掉。
于是得到第 \(t\) 轮的近似目标函数:
这就是 LightGBM / XGBoost 推导中的核心公式。
2.5 这个近似为什么好用?
因为它把原本复杂的函数优化问题,转换成了:
- 树结构决定哪些样本分到同一叶子;
- 每个叶子只需聚合梯度和 Hessian;
- 然后对叶子输出值做简单的二次优化。
换句话说,训练树时真正依赖的不是原始标签本身,而是每个节点中累计的:
这也是 LightGBM 能高效实现 histogram、快速分裂搜索的理论基础。
与实现层面强相关的参数:
max_bin:因为分桶后,每个 bin 上都可以聚合梯度统计量min_sum_hessian_in_leaf:直接约束叶子上的 Hessian 和min_gain_to_split:根据目标下降量决定是否分裂
3. LGBM 叶子输出与分裂增益的表达式推导
这一部分是在上一节近似目标的基础上,继续往下推导两个最经典的公式:
- 最优叶子输出值
- 分裂增益(split gain)
3.1 把树写成“叶子常数输出”的形式
假设第 \(t\) 棵树有 \(J\) 个叶子。对任意样本 \(x_i\),它最终会落到某个叶子上。
记:
- \(q(x_i)\):样本 \(x_i\) 落到的叶子编号
- \(w_j\):第 \(j\) 个叶子的输出值
那么树函数可以表示为:
也就是说:树的预测本质上就是“把样本路由到一个叶子,然后输出该叶子的常数值”。
和这一步最相关的参数:
num_leavesmax_depth
它们决定了 \(q(x)\) 的复杂程度,也就是样本会被划分成多少个区域。
3.2 将近似目标函数按叶子分组
我们已经有:
树的正则项写成:
代入 \(f_t(x_i) = w_{q(x_i)}\),得到:
设第 \(j\) 个叶子的样本集合为 \(I_j\),则可按叶子重写为:
定义该叶子的梯度和 Hessian 统计量:
则目标函数可化简为:
这一步非常关键,因为它说明:
一旦树结构固定,优化问题就分解成了每个叶子的独立二次函数最小化问题。
与这一步最相关的参数:
lambda_l2/reg_lambdanum_leavesmin_sum_hessian_in_leaf
3.3 推导最优叶子输出值
只看第 \(j\) 个叶子对应的目标项:
这是一个关于 \(w_j\) 的一元二次函数。
对 \(w_j\) 求导:
令导数为 0:
解得最优叶子输出:
这就是 LightGBM / XGBoost 中最经典的叶子值公式。
直观理解
- 如果某个叶子里的样本整体预测偏大,则通常 \(G_j > 0\),于是 \(w_j^* < 0\),说明要把预测往下修正;
- 如果整体预测偏小,则通常 \(G_j < 0\),于是 \(w_j^* > 0\),说明要把预测往上修正。
与该式最相关的参数:
lambda_l2/reg_lambda:分母中的正则项,抑制叶子值过大learning_rate:虽然不影响 \(w_j^*\) 的解析解,但最终真正加到模型上的修正量是 \(\eta w_j^*\)
3.4 推导叶子的最优目标值
将:
代回:
先看第一项:
第二项:
两项相加:
因此,一个叶子在最优情况下对目标函数的贡献为:
于是整棵树在结构固定时的最优目标可写成:
这里 \(q\) 表示树结构。
直观理解
因为训练目标是“最小化”,所以这个值越小越好,也就是越负越好。
在实现里,常把:
看成叶子的“收益”或“score 基础项”。
与该式最相关的参数:
lambda_l2/reg_lambdanum_leavesmin_gain_to_split
3.5 推导分裂增益(split gain)
现在考虑一个节点是否值得继续分裂。
设当前节点样本集合为 \(I\),定义:
如果它不分裂,直接作为一个叶子,则对应最优目标值为:
如果它分裂成左右两个叶子,分别记统计量为:
则左右叶子的最优目标值分别是:
同时,分裂会引入额外复杂度代价 \(\gamma\)。
因此,定义分裂增益为:
代入得到:
整理得:
又因为:
所以常写成:
这就是 LightGBM 的分裂增益公式。
3.6 分裂增益公式的直观理解
这个公式本质上就是:
因此,只有当:
- 左右子叶分别拟合的收益之和,比父节点整体拟合更大;
- 并且这部分额外收益足以覆盖复杂度惩罚;
这个分裂才值得发生。
与分裂增益最相关的参数:
min_gain_to_split:只有当增益足够大时才允许分裂lambda_l2/reg_lambda:影响收益计算min_data_in_leaf/min_child_samples:限制分裂后叶子的样本数min_sum_hessian_in_leaf/min_child_weight:限制分裂后叶子的 Hessian 和num_leaves:限制树整体还能继续分裂多少次
3.7 在平方损失下的特殊解释:和“拟合残差”如何对应?
如果回归损失为平方误差:
则:
所以对于叶子 \(j\):
代入最优叶子输出公式:
当忽略正则项时,有:
这说明:
平方损失下,一个叶子的输出值本质上接近于该区域内样本的平均残差修正量。
这也就是为什么大家常用“GBDT 每轮拟合残差”来帮助直观理解 boosting。
与这个理解直接相关的参数:
objective='regression'learning_ratelambda_l2
4. 参数视角下的整体串联
把前面三部分合起来,可以把 LGBM 回归训练过程理解为下面这条链路:
4.1 决定优化什么
由 objective 决定损失函数形式,也就决定:
- 梯度 \(g_i\)
- Hessian \(h_i\)
- 训练时每一轮树到底在纠正什么
常见组合:
objective='regression':平方误差回归objective='regression_l1':绝对误差回归objective='huber':鲁棒回归metric='rmse'/metric='l2'/metric='mae':验证指标
4.2 决定每棵树能长成什么样
由下列参数共同控制树结构:
num_leavesmax_depthmin_data_in_leafmin_sum_hessian_in_leafmin_gain_to_split
这些参数共同决定:
- 一个节点是否继续分裂
- 一棵树最终有多少个叶子
- leaf-wise 生长会不会过深
4.3 决定每个叶子修正多少
由公式:
以及参数:
lambda_l2learning_rate
共同决定。
其中:
lambda_l2控制叶子值不要过大learning_rate控制每棵树真正写入模型的步长
4.4 决定训练多久停止
由:
n_estimators/num_iterationsearly_stopping_roundmetric
共同决定。
这部分对应“boosting 做多少轮”的问题。
5. 一段适合复习或写作业的总结
LightGBM 用于回归时,本质上是在做基于二阶近似的梯度提升决策树学习。训练开始时,模型先给出一个常数初始预测;在第 \(t\) 轮 boosting 中,新增一棵树 \(f_t(x)\),使预测更新为:
为了优化这一轮新增树,LightGBM 不直接最小化原始目标,而是在当前预测附近对损失函数进行二阶泰勒展开,将目标近似为:
将树表示为叶子常数输出形式后,定义每个叶子的梯度和 Hessian 统计量:
则最优叶子输出值为:
进一步可得节点分裂的增益为:
因此,LightGBM 的训练过程可以概括为:
- 由
objective决定损失、梯度与 Hessian; - 由
num_leaves、max_depth、min_data_in_leaf、min_gain_to_split等参数控制树结构; - 由
lambda_l2控制叶子值正则; - 由
learning_rate控制每轮修正步长; - 由
n_estimators与early_stopping_round控制 boosting 轮数与停止时机。
6. 常用参数速查表(回归场景)
| 作用 | 参数 | 含义 |
|---|---|---|
| 目标函数 | objective |
决定损失函数、梯度与 Hessian |
| 验证指标 | metric |
决定训练中监控的评价指标 |
| 提升轮数 | n_estimators / num_iterations |
决定总共训练多少棵树 |
| 学习率 | learning_rate |
控制每棵树对最终模型的贡献 |
| 树复杂度 | num_leaves |
控制叶子数量上限 |
| 树深限制 | max_depth |
防止 leaf-wise 过深 |
| 叶子最少样本数 | min_data_in_leaf / min_child_samples |
防止叶子过小 |
| 叶子最小 Hessian 和 | min_sum_hessian_in_leaf / min_child_weight |
防止不稳定分裂 |
| 最小分裂增益 | min_gain_to_split |
增益不足时不分裂 |
| L2 正则 | lambda_l2 / reg_lambda |
控制叶子输出值大小 |
| L1 正则 | lambda_l1 / reg_alpha |
稀疏化叶子权重(扩展项) |
| 分桶数 | max_bin |
histogram 近似时的桶数 |
| 特征采样 | feature_fraction |
每轮随机采样部分特征 |
| 样本采样 | bagging_fraction、bagging_freq |
每轮随机采样部分样本 |
| 提前停止 | early_stopping_round |
验证集若干轮不提升则停止 |

浙公网安备 33010602011771号