GBDT系列八股(XGBoost、LightGBM)

0. 写在前面

2026/3/17:

搜广推复习过程中,项目用到了树模型,但是一点不会,遂配合DeepSeek尽可能完整的整理八股


1. GBDT

训练出一棵树的基础上,再训练下一棵树,预测它和真实值之间的差距,累加预测结果

1.1 如何选择分裂特征

分离特征:决策树构建过程中,被选为内部节点分裂依据的输入特征

GBDT树是通过最小化损失函数来构建的,每个节点分裂时都会遍历所有特征,找到最大增益的分裂方式

对于回归问题:增益是基于方差减少或均方误差减少

对于分类问题:增益是基尼指数减少或交叉熵减少

**基尼指数:**从数据集中随机抽取两个样本,其类别标签不一致的概率

对于一个包含K个类别的数据集,基尼指数的计算公式如下:

p_i是数据集中第i个样本所占的比例

**交叉熵:**对于一个包含K个类别的数据集,信息熵的计算公式如下:

p_i是数据集中第i个样本所占的比例

1.2 分裂特征的重要性

GBDT输出特征重要性评分,通常基于

  1. 分裂次数:该特征被选为分裂特征的次数

  2. 增益总和:该特征在所有分裂中带来的总增益

  3. 覆盖度:该特征分裂覆盖的样本数量

1.3 GBDT缺失值如何处理

GBDT(包括XGBoost和LightGBM)可以自动学习缺失值的分裂方向:在寻找最佳分裂特征时,算法会将缺失值分别放入左右子树计算损失,选择最优方向

**例如:**如果缺失值去左子树的增益是+10,去右子树是+5,直接规定所有收入缺失的样本默认走左子树

2. XGBoost

XGBoost在GBDT的基础上,对正则化损失函数 求解和工程实现等角度进行改进,兼顾运行效率和模型泛化性

2.1 算法优化

2.1.1 目标函数:引入正则化项

GBDT只优化损失函数(如平方误差、对数损失),不关心树本身的复杂度

XGBoost增加了正则项,包含 叶子节点数 和 叶子权重的L2模平方

2.1.2 损失函数:二阶泰勒展开

GBDT只使用损失函数的一阶导数(梯度)来近似残差

XGBoost对损失函数进行二阶泰勒展开,同时用一阶导和二阶导。

**XGBoost优势:**保留更多损失函数信息,梯度下降的方向更精准,收敛速度更快,能找到更优解

2.1.3 缺失值处理:自动学习缺失值分裂方向

XGBoost稀疏感知算法,训练时自动学习缺失值的最优分裂方向,免去预处理步骤,还可以捕捉缺失本身可能蕴含的信息(例如收入缺失的人可能没有工作,行为模式不同)

2.2 工程优化

2.2.1 并行化计算

GBDT: 串行生成树

XGBoost:特征并行。在构建单颗树时实现并行,先对特征值进行排序,以块结构存储在内存中。寻找分裂点时,可以并行计算所有特征的增益。

并行化决定了多个特征之间如何同时计算

2.2.2 近似分桶算法

GBDT:遍历所有特征值寻找最优切分点,数据量大时内存消耗大且慢

XGBoost:对于连续特征,不遍历所有值,而是根据二阶导数值作为权重,对特征值进行分桶,只在分位点上寻找分裂点

近似分桶决定了每个特征内部怎么找切分点

2.2.3 剪枝策略

GBDT:通常依赖预剪枝

XGBoost:引入最大深度参数限制(预剪枝),同时支持后剪枝。如果一次分裂带来的增益小于设定的最小损失下降值 γ,会剪掉这次分裂(预剪枝)。

**预剪枝:**在树生长过程中提前停止分裂,比如设置max_length=3,树深到3层就停,或者设置节点样本数小于某个阈值就停

**后剪枝:**先把树完全长成,然后自底向上考察非叶子节点,如果把某个子树砍掉能让验证集误差下降就执行

2.3 高频问题

2.3.1 XGBoost为什么要用二阶导而不是一阶导

二阶导数包含损失函数的曲率信息,只用一阶导相当于用直线去拟合残差,而用二阶导数相当于用抛物线去拟合,精度更高,梯度下降方向更准确。

2.3.2 XGBoost的并行化体现在哪里

XGBoost的并行不是树与树之间的并行,GBDT都是串行的,而是特征维度的并行。在训练同一颗树的同一层时,由于各个特征的分裂点搜索是独立的,XGBoost可以将数据预先排序存储为块,然后多线程同时计算所有特征的增益,选择最大增益的特征进行分裂

2.3.3 XGBoost如何处理类别特征

早期XGBoost默认将所有输入视为数值型,因此处理类别特征需要手动预处理

1)独热编码:将类别特征展开为多个01虚拟变量。缺点是维度爆炸、稀疏性、失去顺序信息

2)标签编码:将类别映射为整数(如红=1,蓝=2)。缺点是给类别强加不存在的关系

从XGBoost 1.6版本开始,官方引入对类别特征的原生实验性支持。通过指定`enable_categorical = True`参数,并将DataFrame中的类别列类型设未pandas.Categorical或使用feature_types指定。

启动原生支持后,XGBoost采用分区法:

1)统计:计算每个类别对应的一阶导和二阶导的统计量

2)排序:根据统计量对类别进行排序

3)寻找最优划分:在排序后的类别表上,寻找最优的切分点

3. LightGBM

LightGBM是一个基于直方图算法的梯度提升框架,针对XGBoost在大数据场景下的训练速度慢、内存消耗大的问题进行了系统性优化

3.1 决策树生长策略

|------|----------------|---------------|
| 维度 | XGBoost | LightGBM |
| 生长策略 | Level-Wise | Leaf-Wise |
| 示意图 | 每层所有节点同时分裂 | 每次只找增益最大的叶子分裂 |
| 特点 | 并行容易,控制深度防止过拟合 | 效率高,但可能过拟合 |

LightGBM的Wise-Level:

每次从当前所有叶子中,找到分裂增益最大的那个叶子进行分裂,其他叶子不动

优点:效率更高,误差更小,每次都在优化最需要分裂的位置

缺点:可能长出不平衡的树,容易过拟合,需要配合最大深度限制来控制

3.2 分裂点寻找算法

|----|----------|--------------------|
| | XGBoost | LightGBM |
| 算法 | 预排序算法 | 直方图算法 |
| 做法 | 遍历所有特征值 | 将连续特征离散化成k个桶,构建直方图 |
| 内存 | 大(存排序索引) | 小(存离散值) |
| 速度 | 慢(遍历所有值) | 快(只遍历k个桶) |

LightGBM将连续特征离散化成k(0-255)个整数,构建一个包含k个bin(桶)的直方图,分裂时只需要遍历k个bin(桶),而不是n个样本

3.3 GOSS和EFB

3.3.1 GOSS基于梯度的单边采样

问题:样本量太大,计算每个样本的梯度很耗时

做法:保留大梯度的样本(对计算信息增益贡献大),对小梯度的样本进行随机采样

3.3.2 EFB互斥特征捆绑

问题:特征维度太高

做法:将互斥(几乎不同时非零)特征捆绑成一个新特征

3.4 类别特征处理

XGBoost:传统版本需要独热编码,新版本虽然已支持但是成熟度不如LightGBM

LightGBM:使用直方图算法对类别进行按梯度统计量排序,然后寻找最优分裂

3.5 高频问题

3.5.1 LightGBM的leaf-wise生长为什么容易过拟合

每次只分裂增益最大的叶子,会导致树不平衡。

解决方案:设置最大深度限制、设置总叶子节点数

3.5.2 直方图算法的优缺点

优点:内存占用小;计算速度快;有利于差分计算;离散化本身是一种平滑,防止过拟合

缺点:丢失信息,损失精度

3.5.3 GOSS为什么有效,会不会丢信息

因为大梯度样本对计算信息增益贡献最大,小梯度样本贡献较小,采样一部分即可代表整体分布

相关推荐
bryant_meng2 小时前
【AI】《Explainable Machine Learning》
人工智能·深度学习·机器学习·计算机视觉·可解释性
CoderIsArt2 小时前
StarCoder-3B微调和RAG的技术原理
人工智能·深度学习·机器学习
hans汉斯2 小时前
基于区块链和语义增强的科研诚信智能管控平台
人工智能·算法·yolo·数据挖掘·区块链·汉斯出版社
冷小鱼2 小时前
机器学习极简入门:从外卖预测到AI核心算法
人工智能·算法·机器学习
yinyan13142 小时前
一起学springAI系列一:使用多种聊天模型
java·人工智能·spring boot·后端·spring·springai
冷小鱼2 小时前
Word2Vec 揭秘:如何让计算机“理解“词语?
人工智能·自然语言处理·word2vec
技术小甜甜2 小时前
[Python实战] 用 pathlib 彻底统一文件路径处理,比字符串拼接稳得多
开发语言·人工智能·python·ai·效率化
未来之窗软件服务2 小时前
二次训练中文 NLU小体积[AI人工智能(五十九)]—东方仙盟
人工智能·仙盟创梦ide·东方仙盟
landuochong2002 小时前
用 Telegram 远程控制你本地的 Claude Code
人工智能·架构·claudecode