Day 10:集成学习进阶(Boosting: AdaBoost, GBDT)
📋 目录
- Boosting 基础原理
- AdaBoost 算法详解
- 梯度提升机 (GBDT) 原理
- AdaBoost vs GBDT vs 随机森林
- GBDT 核心超参数
- 损失函数与优化
第一部分:Boosting 基础原理(1.5小时理论)
1.1 什么是 Boosting?
定义 :Boosting 是一种将多个弱学习器串行 组合成强学习器的集成方法,每个新模型都关注前一个模型犯错的样本。
核心思想 :三个臭皮匠,通过递进式学习变成诸葛亮。
与 Bagging 的核心区别:
| 特性 | Bagging (随机森林) | Boosting (AdaBoost/GBDT) |
|---|---|---|
| 训练方式 | 并行训练 | 串行训练 |
| 样本权重 | 均匀采样 | 动态调整权重 |
| 模型权重 | 平等投票 | 根据性能加权 |
| 目标 | 降低方差 | 降低偏差 |
| 过拟合风险 | 较低 | 较高(需调参) |
1.2 Boosting 的工作流程
text
初始化样本权重 (均匀)
↓
训练弱学习器 h₁
↓
计算 h₁ 的误差,更新样本权重(错误样本权重↑)
↓
训练弱学习器 h₂(关注上一轮错误样本)
↓
计算 h₂ 的误差,更新样本权重
↓
... 重复 T 次 ...
↓
加权组合所有弱学习器得到最终强学习器
1.3 Boosting 的数学原理
加法模型 :
F(x)=∑t=1Tαtht(x) F(x)= \sum_{t=1}^T \alpha_th_t(x) F(x)=t=1∑Tαtht(x)
其中:
- hth_tht:第 ttt 个弱学习器
- αt\alpha_tαt:第 ttt 个学习器的权重(表现越好,权重越大)
前向分步算法 :
Ft(x)=Ft−1(x)+αtht(x) F_t(x)=F_{t−1}(x) + \alpha_th_t(x) Ft(x)=Ft−1(x)+αtht(x)
每一步最小化损失函数:
(αt,ht)=argminα,h∑i=1nL(yi,Ft−1(xi)+αh(xi)) (\alpha_t,h_t) = \text{argmin}{\alpha,h} \sum{i=1}^n L(y_i, F_{t−1}(x_i) + \alpha h(x_i)) (αt,ht)=argminα,hi=1∑nL(yi,Ft−1(xi)+αh(xi))
1.4 Boosting 的优缺点
优点:
- 高精度:通常优于 Bagging
- 灵活:可使用多种损失函数
- 特征重要性:自动评估
缺点:
- 对异常值敏感
- 训练较慢(串行)
- 容易过拟合(需仔细调参)
第二部分:AdaBoost 算法详解
2.1 AdaBoost 原理
AdaBoost (Adaptive Boosting,自适应增强) :第一个实用的 Boosting 算法,通过调整样本权重 和基学习器权重实现。
算法步骤:
-
初始化样本权重 (假设共有 nnn 个样本):
w1(i)=1n,i=1,2,...,n w_1^{(i)} = \frac{1}{n}, \quad i = 1, 2, \dots, n w1(i)=n1,i=1,2,...,n -
迭代训练弱分类器(进行 T 轮迭代,对于 t = 1 到 T):
-
训练弱学习器 hth_tht(使用权重 wtw_twt)
-
计算加权误差率:
ϵt=∑i=1nwt(i)⋅I(ht(xi)≠yi)∑i=1nwt(i) \epsilon_t = \frac{\sum_{i=1}^n w_t^{(i)} \cdot \mathbb{I}(h_t(x_i) \neq y_i)}{\sum_{i=1}^n w_t^{(i)}} ϵt=∑i=1nwt(i)∑i=1nwt(i)⋅I(ht(xi)=yi) -
计算学习器权重:
αt=12ln(1−ϵtϵt) \alpha_t = \frac{1}{2} \ln \left( \frac{1 - \epsilon_t}{\epsilon_t} \right) αt=21ln(ϵt1−ϵt)
ϵt\epsilon_tϵt 越小,αt\alpha_tαt 越大。 -
更新样本权重:
wt+1(i)=wt(i)⋅exp(−αtyiht(xi)) w_{t+1}^{(i)} = w_t^{(i)} \cdot \exp \left( -\alpha_t y_i h_t(x_i) \right) wt+1(i)=wt(i)⋅exp(−αtyiht(xi))这里二分类标签为 1 或 -1,所以 实际值 yiy_iyi 和预测值 ht(xi)h_t(x_i)ht(xi) 取值为 1 或 -1。
-
归一化权重
-
-
输出最终模型 :
H(x)=sign(∑t=1Tαtht(x)) H(x) = \text{sign} \left( \sum_{t=1}^T \alpha_t h_t(x) \right) H(x)=sign(t=1∑Tαtht(x))
2.2 AdaBoost 的权重更新
直观理解:
- 分类错误的样本:权重增加(×eαt\times e^{\alpha_t}×eαt)
- 分类正确的样本:权重减少(×e−αt\times e^{-\alpha_t}×e−αt)
示例:
python
# 假设 α = 0.5
# 错误样本新权重 = 旧权重 × 1.648
# 正确样本新权重 = 旧权重 × 0.607
2.3 AdaBoost 的基学习器
常用基学习器:
- 决策树桩(stump):只有1个分裂节点的决策树(默认)
- 浅层决策树(max_depth=1-3)
为什么用弱学习器:
- 防止过拟合
- 体现 Boosting 的"递进"思想
- 计算效率高
2.4 AdaBoost 的损失函数
指数损失函数 :
L(y,F(x))=exp(−yF(x)) L(y,F(x))=exp(−yF(x)) L(y,F(x))=exp(−yF(x))
特点:
- 对异常值敏感
- 分类边界会偏向困难样本
第三部分:梯度提升机 (GBDT) 原理
3.1 从 AdaBoost 到 GBDT
AdaBoost 的限制:
- 仅支持指数损失(二分类)
- 难以扩展到回归和多分类
GBDT 的突破:
- 任何可微损失函数
- 统一框架:回归、分类、排序
3.2 GBDT 核心思想
关键洞察 :将 Boosting 视为函数空间上的梯度下降
算法流程:
-
初始化:
F0(x)=argminγ∑i=1nL(yi,γ) F_0(x) = \arg\min_{\gamma} \sum_{i=1}^n L(y_i, \gamma) F0(x)=argγmini=1∑nL(yi,γ) -
对于 m = 1 到 M:
-
计算负梯度(伪残差) :
rim=−[∂L(yi,F(xi))∂F(xi)]F=Fm−1 r_{im} = - \left[ \frac{\partial L(y_i, F(x_i))}{\partial F(x_i)} \right]{F=F{m-1}} rim=−[∂F(xi)∂L(yi,F(xi))]F=Fm−1 -
训练回归树 hm(x)h_m(x)hm(x) 拟合伪残差 (xi,rim){(x_i, r_{im})}(xi,rim)
-
计算最优步长:
γm=argminγ∑i=1nL(yi,Fm−1(xi)+γhm(xi)) \gamma_m = \arg\min_{\gamma} \sum_{i=1}^n L(y_i, F_{m-1}(x_i) + \gamma h_m(x_i)) γm=argγmini=1∑nL(yi,Fm−1(xi)+γhm(xi)) -
更新模型:
Fm(x)=Fm−1(x)+ν⋅γmhm(x) F_m(x) = F_{m-1}(x) + \nu \cdot \gamma_m h_m(x) Fm(x)=Fm−1(x)+ν⋅γmhm(x)
-
-
输出 FM(x)F_M(x)FM(x)
3.3 伪残差的直观理解
伪残差 :损失函数对预测值的负梯度,表示当前模型预测的错误方向和程度。
不同损失函数的伪残差:
| 损失函数 | 伪残差公式 | 说明 |
|---|---|---|
| 平方损失(回归) | r=y−F(x)r = y - F(x)r=y−F(x) | 真实残差 |
| 绝对损失(回归) | r=sign(y−F(x))r = \text{sign}(y - F(x))r=sign(y−F(x)) | 符号残差 |
| 对数损失(分类) | r=y−p(x)r = y - p(x)r=y−p(x) | 概率残差 |
3.4 学习率(Shrinkage)
学习率 ν\nuν :控制每棵树的贡献,防止过拟合。
Fm(x)=Fm−1(x)+μ⋅γmhm(x) F_m(x)=F_{m−1}(x) + \mu ⋅ \gamma_m h_m(x) Fm(x)=Fm−1(x)+μ⋅γmhm(x)
典型值:0.01 - 0.1
效果:
- 小学习率 + 多棵树 = 更好泛化
- 需要更多训练时间
第四部分:AdaBoost vs GBDT vs 随机森林
4.1 三者的核心区别
| 特性 | 随机森林 | AdaBoost | GBDT |
|---|---|---|---|
| 集成方式 | Bagging(并行) | Boosting(串行) | Boosting(串行) |
| 样本采样 | Bootstrap(均匀) | 加权采样 | 全部使用(加权) |
| 基学习器 | 完整决策树 | 决策树桩 | 浅层决策树 |
| 模型权重 | 平等 | 根据误差加权 | 学习率控制 |
| 过拟合风险 | 低 | 中 | 中高 |
| 对异常值 | 鲁棒 | 敏感 | 中等 |
| 可解释性 | 中等 | 较差 | 较差 |
4.2 性能对比
| 数据集类型 | 推荐算法 | 原因 |
|---|---|---|
| 高维稀疏 | 随机森林 | 对噪声特征鲁棒 |
| 低维稠密 | GBDT | 能捕捉复杂交互 |
| 有异常值 | 随机森林 | 对异常值不敏感 |
| 需要概率输出 | GBDT | 天然支持概率 |
| 小数据集 | AdaBoost | 不易过拟合 |
4.3 选择指南
python
# 决策树
if 需要可解释性:
if 数据量小:
return "决策树"
else:
return "随机森林(可解释性较弱)"
if 追求最高精度:
if 数据量大:
return "XGBoost / LightGBM(GBDT变体)"
else:
return "GBDT / AdaBoost"
if 对异常值敏感:
return "随机森林"
if 特征维度高且稀疏:
return "随机森林 / 线性模型"
第五部分:GBDT 核心超参数
5.1 关键参数
| 参数 | 含义 | 典型值 | 影响 |
|---|---|---|---|
n_estimators |
树的数量 | 100-1000 | 越多越稳定 |
learning_rate |
学习率 | 0.01-0.1 | 越小越需要更多树 |
max_depth |
最大深度 | 3-8 | 控制交互复杂度 |
min_samples_split |
分裂最小样本数 | 2-20 | 正则化 |
subsample |
子采样比例 | 0.5-1.0 | 随机性,防过拟合 |
loss |
损失函数 | 'log_loss' | 任务类型 |
5.2 参数交互
学习率与树数量的权衡:
python
# 大学习率 + 少树
gbdt = GradientBoostingClassifier(learning_rate=0.3, n_estimators=50)
# 小学习率 + 多树(通常更好)
gbdt = GradientBoostingClassifier(learning_rate=0.05, n_estimators=300)
经验法则:
- 学习率 × 树数量 ≈ 常数
- 小学习率(<0.1)通常更好
5.3 正则化参数
| 参数 | 作用 | 建议 |
|---|---|---|
subsample |
每次迭代采样比例 | 0.5-0.8 |
max_depth |
限制树深度 | 3-6 |
min_samples_split |
分裂最小样本 | 5-20 |
min_samples_leaf |
叶节点最小样本 | 2-10 |
max_features |
特征子集 | 'sqrt' |
第六部分:损失函数与优化
6.1 常用损失函数
| 任务 | 损失函数 | sklearn参数 | 说明 |
|---|---|---|---|
| 二分类 | 对数损失 | loss='log_loss' |
输出概率 |
| 二分类 | 指数损失 | loss='exponential' |
类似AdaBoost |
| 回归 | 平方损失 | loss='ls' |
对异常值敏感 |
| 回归 | 绝对损失 | loss='lad' |
鲁棒 |
| 回归 | Huber损失 | loss='huber' |
平衡 |
6.2 损失函数选择
python
# 二分类(默认,推荐)
gbdt = GradientBoostingClassifier(loss='log_loss')
# 类似AdaBoost(对异常值更敏感)
gbdt = GradientBoostingClassifier(loss='exponential')
# 回归 - 平方损失
gbr = GradientBoostingRegressor(loss='ls')
# 回归 - 绝对损失(鲁棒)
gbr = GradientBoostingRegressor(loss='lad')
6.3 早停(Early Stopping)
原理:当验证集性能不再提升时停止训练。
python
gbdt = GradientBoostingClassifier(
n_estimators=1000,
validation_fraction=0.1, # 10%数据作为验证集
n_iter_no_change=10, # 10轮不提升则停止
tol=1e-4 # 提升阈值
)