文档
LightGBM 入门教程:Leaf-wise 生长与 GOSS 原理
1. LightGBM 的设计哲学
LightGBM 的三个核心问题:
"XGBoost 在大数据上太慢了,内存也吃不起。能不能更快、更省?"
答案:三个算法创新 —— Leaf-wise / GOSS / EFB。
2. Leaf-wise vs Level-wise
XGBoost (Level-wise): LightGBM (Leaf-wise):
[A] [A]
/ \ |
[B] [C] [B] ← 只分裂增益最大的叶子
/ \ / \ / \
[D][E] [F][G] [D] [E]
Level-wise 每层所有节点都分裂(很多没必要),Leaf-wise 只分裂增益最大的叶节点:
- 相同叶子数下误差更低
- 速度快 10-20x
- 但易过拟合 → 需限制
max_depth和num_leaves
关键约束参数
num_leaves=31 # 最大叶子数(LightGBM 核心参数)
max_depth=-1 # 限制深度防止过拟合,-1 不限制
min_data_in_leaf=20 # 叶子最少样本数
⚠️ 调大
num_leaves效果可能先升后降——典型过拟合信号。
3. GOSS:基于梯度的单边采样
动机:梯度小的样本已被学好了,梯度大的才需要重点关注。
算法:
- 按梯度绝对值排序
- 保留 top a% 大梯度样本
- 从剩余样本中随机采样 b%
- 对 b% 样本乘以 (1-a)/b 补偿
参数:
boosting_type='gbdt' # 默认即使用 GOSS
top_rate=0.2 # a(大梯度保留比例)
other_rate=0.1 # b(小梯度采样比例)
4. EFB:互斥特征绑定
很多特征互斥(不同时为非零),如 One-Hot 编码后的类别。EFB 将它们捆绑为单个特征,减少直方图构建开销。
# 自动启用,无需手动设置
# 等效效果:100 个 One-Hot 列 → 合并为 ~20 个特征束
5. 原生类别特征:不用 One-Hot!
# ❌ XGBoost 需要这样(特征膨胀!)
pd.get_dummies(df, columns=['city'])
# ✅ LightGBM 原生支持
df['city'] = df['city'].astype('category')
model.fit(X, y, categorical_feature=['city'])
内部机制:对类别值求目标变量均值排序,再找最优分割点。既省内存,又更准。
6. 常见超参数调优指南
# 快速开始模板
lgb.LGBMClassifier(
n_estimators=500,
learning_rate=0.05,
num_leaves=31, # < 2^max_depth
max_depth=7,
min_child_samples=20,
subsample=0.8,
colsample_bytree=0.8,
reg_alpha=0.1, # L1
reg_lambda=0.1, # L2
)
7. LightGBM vs XGBoost 选型
| 场景 | 推荐 |
|---|---|
| 数据 < 10 万行 | XGBoost(更稳定) |
| 数据 > 100 万行 | LightGBM |
| 类别特征多 | LightGBM |
| 需极致精度 | XGBoost(更保守,不易过拟合) |
| 特征维度高(>1000) | LightGBM(EFB) |
思考题
- Leaf-wise 为什么比 Level-wise 更快?是算法原因还是工程原因?
- GOSS 采样会引入偏差,LightGBM 如何修正这个偏差?
- 为什么
num_leaves设太大反而验证集效果下降?