Day 10:集成学习进阶(Boosting: AdaBoost, GBDT)

Day 10:集成学习进阶(Boosting: AdaBoost, GBDT)

📋 目录

  1. Boosting 基础原理
  2. AdaBoost 算法详解
  3. 梯度提升机 (GBDT) 原理
  4. AdaBoost vs GBDT vs 随机森林
  5. GBDT 核心超参数
  6. 损失函数与优化

第一部分: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)=arg⁡minα,h∑i=1nL(yi,Ft−1(xi)+αh(xi)) (\alpha_t,h_t) = \text{arg⁡min}{\alpha,h} \sum{i=1}^n L(y_i, F_{t−1}(x_i) + \alpha h(x_i)) (αt,ht)=arg⁡minα,hi=1∑nL(yi,Ft−1(xi)+αh(xi))

1.4 Boosting 的优缺点

优点:

  • 高精度:通常优于 Bagging
  • 灵活:可使用多种损失函数
  • 特征重要性:自动评估

缺点:

  • 对异常值敏感
  • 训练较慢(串行)
  • 容易过拟合(需仔细调参)

第二部分:AdaBoost 算法详解

2.1 AdaBoost 原理

AdaBoost (Adaptive Boosting,自适应增强) :第一个实用的 Boosting 算法,通过调整样本权重 和基学习器权重实现。

算法步骤:

  1. 初始化样本权重 (假设共有 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

  2. 迭代训练弱分类器(进行 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。

    • 归一化权重

  3. 输出最终模型 :
    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 视为函数空间上的梯度下降

算法流程:

  1. 初始化:
    F0(x)=arg⁡min⁡γ∑i=1nL(yi,γ) F_0(x) = \arg\min_{\gamma} \sum_{i=1}^n L(y_i, \gamma) F0(x)=argγmini=1∑nL(yi,γ)

  2. 对于 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=arg⁡min⁡γ∑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)

  3. 输出 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                   # 提升阈值
)
相关推荐
weixin_307779132 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
每天都要写算法(努力版)5 小时前
【行业前沿报告】DAgger:让智能体在自己走到的状态上学习
人工智能·学习·机器学习
小小龙学IT5 小时前
Python scikit-learn 机器学习库深度解析
python·机器学习·scikit-learn
FL16238631297 小时前
智慧医疗X光图像小儿手腕外伤检测数据集VOC+YOLO格式2538张9类别
人工智能·yolo·机器学习
hetao17338377 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia6267 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan8 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
xx_xxxxx_8 小时前
论文阅读-SAR
人工智能·深度学习·机器学习
2601_960356389 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah9 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分