楼层: 首页/ 软件技术/ Python 机器学习与深度学习/ 梯度提升树:XGBoost / LightGBM / CatBoost
6

梯度提升树:XGBoost / LightGBM / CatBoost

GBDT Trio: XGBoost, LightGBM, CatBoost

表格数据的"王者"三件套。Kaggle 表格赛里,这三家刷了半个世纪的榜单。理解 GBDT 原理是面试和实战的分水岭。

GBDT 原理

论串行纠错

GBDT 像"补课":第一棵树学个大概,第二棵树专门拟合第一棵树的残差(预测和真实值的差),第三棵树拟合前两棵的残差……最后把所有树的输出加起来。每棵树都很浅(3~8 层),叫"弱学习器"。Shinkage(学习率):每棵树的贡献乘一个小系数(0.01~0.1),让多棵树慢慢修正,过拟合更少。

GBDT 直观例子:拟合残差

# 假设真实关系 y = 3x + 噪声,我们用 GBDT 拟合 # 第 0 轮:用均值预测 y_pred_0 = y.mean() residual_1 = y - y_pred_0 # 残差 = 真实 - 预测 # 第 1 棵树:拟合残差 residual_1 tree1 = DecisionTreeRegressor(max_depth=2) tree1.fit(X, residual_1) y_pred_1 = y_pred_0 + 0.1 * tree1.predict(X) # 学习率 0.1 # 第 2 棵树:拟新残差 residual_2 = y - y_pred_1 tree2 = DecisionTreeRegressor(max_depth=2) tree2.fit(X, residual_2) y_pred_2 = y_pred_1 + 0.1 * tree2.predict(X) # 重复几百轮,每棵树都修正前面的错误 # XGBoost 把这个过程工程化:正则化 + 二阶导 + 并行

XGBoost:极致优化的 GBDT

论陈天奇的工程魔法

XGBoost 比原生 GBDT 强在:① 正则化项(叶子数 + 叶子权重,防过拟合);② 二阶泰勒展开(同时用一阶梯度和二阶梯度,收敛更快);③ 缺失值自动处理(学一个默认方向);④ 列块并行(特征排序预先分块);⑤ 近似分裂(大数据不找精确分裂点)。

from xgboost import XGBRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error import numpy as np # 假设 X, y 已经准备好 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) model = XGBRegressor( n_estimators=500, # 树的数量 max_depth=6, # 每棵树最大深度 learning_rate=0.05, # shrinkage subsample=0.8, # 每棵树用 80% 样本 colsample_bytree=0.8, # 每棵树用 80% 特征 reg_alpha=0.1, # L1 正则 reg_lambda=1.0, # L2 正则 early_stopping_rounds=20, # 20 轮不提升就停 random_state=42, n_jobs=-1 ) model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=50) pred = model.predict(X_test) print(f"RMSE: {np.sqrt(mean_squared_error(y_test, pred)):.4f}") # 特征重要性 for name, imp in zip(model.feature_names_in_, model.feature_importances_): if imp > 0.01: print(f" {name}: {imp:.3f}")

LightGBM:又快又省内存

论微软的两个绝活

① 直方图算法:把连续特征分桶(比如 256 个桶),分裂点只在桶边界找,速度快一个数量级。② Leaf-wise(leaf 优先生长):每次从当前所有叶子里挑损失下降最大的那个分裂,而不是整层一起长(XGBoost 默认 Level-wise)。③ GOSS 单边梯度采样:保留大梯度样本、随机采小梯度样本。④ EFB 互斥特征捆绑:把稀疏特征绑一起降维。

from lightgbm import LGBMClassifier lgbm = LGBMClassifier( n_estimators=500, num_leaves=31, learning_rate=0.05, feature_fraction=0.8, bagging_fraction=0.8, min_child_samples=20, random_state=42 ) lgbm.fit(X_train, y_train, eval_set=[(X_test, y_test)])

CatBoost:类别特征全自动

论Yandex 的贡献

CatBoost 最大卖点:类别特征不用你 One-Hot,直接喂进去,它内部用有序目标编码(Ordered Target Encoding)处理,避免目标泄漏。有序提升(Ordered Boosting):每棵树用不同的样本顺序训练,减少预测偏移。对称树:所有叶子同深度,预测快。

三巨头对比

维度XGBoostLightGBMCatBoost
速度中最快中
内存中最省中
类别特征需自己编码支持但要声明原生支持,最强
精度强强强(调参少时 often 第一)
调参难度中中最简单(默认就好)
小数据集好可能过拟合好

XGBoost 关键超参速查

参数常用值作用
n_estimators100~1000树的数量,配 early_stopping_rounds。
max_depth3~8每棵树深度,越大越易过拟合。
learning_rate0.01~0.1shrinkage,小要配多树。
subsample0.7~1.0每棵树用多少样本,防过拟合。
colsample_bytree0.7~1.0每棵树用多少特征。
reg_alpha / reg_lambda0.1 / 1.0L1 / L2 正则。
gamma0~5分裂所需最小损失下降,防过拟合。

本章面试题

面试 · GBDT

Q1. GBDT 和随机森林都用树,区别?

查看答案

随机森林是 Bagging(并行投票,降方差);GBDT 是 Boosting(串行拟合残差,降偏差)。前者树深、并行;后者树浅、串行。

Q2. XGBoost 比原生 GBDT 多了什么?

查看答案

正则化项、二阶泰勒展开、缺失值处理、列块并行、近似分裂算法。

Q3. learning_rate 调大还是调小?

查看答案

小(0.01~0.1)更稳但要更多树;大(0.3+)快但容易过拟合。常用 0.05,配合 early stopping。

Q4. Leaf-wise vs Level-wise?

查看答案

Level-wise 整层一起长(XGBoost 默认),稳但慢;Leaf-wise 只长损失降最多的叶子(LightGBM),快但小数据易过拟合,要配 min_child_samples。