LightGBM 如何用直方图生长一棵树
上一节已经知道怎样评价一刀。现在的问题是:样本和特征很多时,如何更便宜地枚举候选,又该先切哪片叶子?
本页固定 LightGBM 4.6.0 的 CPU、普通 GBDT、常数叶。沿用四行数据和初始梯度 [1,1,-1,-1],关注样本统计如何流入一次分裂。
1. 从原始数值到 bin
手写树对原始不同值逐个枚举阈值。直方图算法先把数值映射到有限的箱,也就是 bin。箱边界通常在训练数据构建阶段形成,之后树学习复用它们;并非每轮都用标签重新分箱。
为了手算,先假设四个不同数值各占一箱:
| bin | 原始 x | 数量 N | 梯度和 G | Hessian 和 H |
|---|---|---|---|---|
| 0 | 1 | 1 | 1 | 1 |
| 1 | 2 | 1 | 1 | 1 |
| 2 | 3 | 1 | -1 | 1 |
| 3 | 4 | 1 | -1 | 1 |
这是一张特征直方图,不是标签频率图。每个节点、每个被考虑的特征,要汇总该节点样本的梯度统计。本页 N 是教学用的显式计数;库内部不同目标和实现分支可能利用 Hessian 估计数量。
扫描到 bin 1 之后,左侧前缀和是
2. 分箱节省了哪部分工作
构建一列直方图仍要处理节点样本,大致是
压缩也会失去候选。假如把 x=2 和 x=3 合并到一箱,原本的 2.5 就不再是箱间边界。这是速度、内存与切分精细程度之间的取舍,不是箱数越大必然泛化越好。
max_bin 是上限,不保证实际生成这么多箱。样本值分布、分箱最小样本要求和缺失处理也会影响可用边界。
3. 子节点直方图还能相减
父节点已经有直方图,分裂后只为一个孩子从样本重建统计,另一个可以通过:
逐箱得到。通常选择样本较少的孩子构建,减少扫描。这个等式依赖三者使用相同分箱定义,并且两个孩子恰好把父节点样本分完。
检查点:上表父节点每箱 H=1。如果左孩子只包含 x=1、2,左直方图 H 为 [1,1,0,0],相减得到右侧 [0,0,1,1]。负计数或不守恒的梯度和都应触发排查。
4. 叶子优先回答另一个问题
“在哪个阈值切”与“下一次切哪个叶子”是两个层次。LightGBM 的叶子优先生长会为可切叶子维护最佳候选,然后选择增益最大的那个继续分裂。
当前叶子 A:最佳合法增益 0.8
当前叶子 B:最佳合法增益 2.1 ← 下一次选择
当前叶子 C:没有合法正增益 ← 保持叶子这里是说明调度的独立数值示意,不是四行数据的第三轮输出。四行例子在一刀后已没有进一步正增益。
逐层生长按深度推进;叶子优先允许在某一侧长出更深路径。num_leaves 限制叶子数,max_depth 限制路径深度,二者不能互相替代。设置深度上限不会把 LightGBM 改成逐层生长。参数配合可参照 官方调参指南。
5. 缺失值也必须有路由
本章手写树拒绝 NaN;LightGBM 可以处理缺失。训练在合法候选中考虑缺失的归属,保存预测时采用的默认方向。
4.6.0 默认使用 NaN 表示缺失,zero_as_missing=false,因此数值 0 通常仍是观测值。只有确认 0 的数据语义就是缺失时,才考虑改变该设置。稀疏矩阵中未存储的位置在默认配置下也按零处理。见 缺失值说明。
“可以路由缺失”不说明缺失机制合理。例如训练数据中的缺失来自某个流程,未来流程改变,模型仍可能失效。它解决输入如何通过树,不自动解决数据来源问题。
6. 类别编码不是连续大小
类别 A、B、C 编码为 0、1、2,若当作普通数值,阈值只能按编码大小切分。声明为类别特征后,算法可以考虑类别集合的划分;高基数情形使用梯度统计排序等策略,小类别数也有相应分支。
在本版接口中应显式指定 categorical_feature,采用稳定的非负整数编码;负值被视为缺失。训练和预测必须保持同一映射,否则同一个整数就会代表不同对象。见 类别特征说明。
7. 进阶:GOSS 与 EFB 放在哪里
它们解决规模问题,主线不要求先实现:
- GOSS 调整用于估计分裂统计的样本:保留大梯度样本,对小梯度部分采样并修正权重。
- EFB 利用稀疏特征很少同时非零的结构进行打包,减少有效特征处理量。
这是 LightGBM 原论文 的主要主题。本版普通训练并不默认开启 GOSS;具体开关查本章速查页。不要把“论文提出某机制”理解为“所有训练都必经这个机制”。
小结、自测与下一步
- 为什么直方图相减必须共用分箱边界?
- 合并 x=2、3 的箱会丢掉哪个候选?
- 为什么
max_depth=3不等于一定生成 8 个叶子?
参考答案
- 相减的每个位置必须描述同一个原始值区间,否则统计没有可比意义。
- 2.5,原本完美区分标签的一刀可能消失。
- 8 只是深度 3 二叉树的叶子上限;样本约束、增益和叶子预算都会让实际树更小。