集成学习方法(Bagging、Boosting、Stacking)

集成学习方法

一、Bagging

Bagging算法,又称装袋算法,最初由Leo Breiman于1966年提出。思想:独立训练多个弱模型,再综合多个弱模型进行共同预测,由此抵抗过拟合,提高模型预测精度。

对训练数据进行有放回采样,生成多个不同的子训练集,然后在这些子训练集上分别训练模型,最后将所有模型的预测结果平均(回归)或投票(分类)

详细步骤:

  1. Bootstrap采样:

    从原始原始训练集 $D={(x1,y1),…,(xn,yn)}$ 中进行有放回地采样,得到$B$个数据集 $D_1,D_2,…,D_B$,每个数据集大小和原始训练集相同。

  2. 模型训练:

    对每个数据集$D_i$训练一个模型$h_i(x)$,通常是决策树

  3. 模型聚合:
    对于回归任务,最终预测值取所有模型的平均值:$\hat f(x)=\frac{1}{B}\sum^{B}_{i=1}h_i(x)$

    对于分类任务,最终预测值是所有模型输出的投票结果:$\hat f(x)=majority_vote{h_i(x)}$

Bagging的优点:通过多个模型的平均减少了模型的偶然误差。抗过拟合效果好,尤其是针对不稳定的模型(如决策树)很有效(Bagging+决策树+特征随机选择=随机森林)。

二、Boosting(提升方法)

思想:在分类问题中,通过改变训练样本的权重,学习多个分类器,并将这些分类器进行线性组合,提高分类性能。

将多个弱分类器(通常是相同类型的分类器)依次训练,并在每次训练时给予前一轮错误分类样本更高的权重,从而使得模型在迭代过程中不断纠正前一轮的错误。

代表算法:AdaBoost(Adaptive Boosting)、Gradient Boosting

1.AdaBoost

通过迭代地调整样本权重,逐步优化分类器的准确度。在每一轮训练中,前一轮错误分类的样本被赋予更大的权重,使得后续分类器会特别关注这些难分类的样本。

Adaboost算法:

训练数据集$T={(x_1,y_1),(x_2,y_2),..,(x_N,y_N)}$,其中$x_i\in R^n,y_i\in Y= {-1,+1}$

  1. 初始化训练数据的权值分布

$D_1=(w_{11},…,w_{1i},..,w_{1N}),w_{1i}=1/N,i=1,2,…,N$

  1. 对$m=1,2,…,M$使用具有权值分布$D_m$的训练数据集学习,得到基本分类器$G_m(x):X\rightarrow{-1,+1}$

  2. 计算$G_m(x)$在训练数据集上的分类误差率$e_m=\sum_{i=1}^Nw_{mi}I(G_m(x_i) \not= y_i)$

  3. 计算$G_m(x)$的系数$\alpha_m=\frac{1}{2}log\frac{1-e_m}{e_m}$,误分率越小,系数越大,该基本分类器在最终分类器中的作用越大

  4. 更新权重分布$D_{m+1=}(w_{m+1,1},…,w_{m+1,i},..,w_{m+1,N})$

    $w_{m+1,i}=\frac{w_{mi}}{Z_m}exp(-\alpha_my_iG_m(x_i))$

    其中$Z_m$是规范化因子$Z_m=\sum_{i=1}^{N}w_{mi}exp(-\alpha_my_iG_m(x_i))$

    使得$D_{m+1}$成为一个概率分布

  5. 构建基本分类器的线性组合$f(x)=\sum_{m=1}^M\alpha_mG_m(x)$

    得到最终分类器$G(x)=sign(f(x))$

  6. 计算组合$f(x)$的误分率,当误分率或迭代次数低于一定与之,停止迭代,否则回到步骤2

AdaBoost能在学习过程中不断减少训练误差。具体由下面的定理

(AdaBoost的训练误差界)AdaBoost最终分类器的训练误差界为:

$\frac{1}{N}\sum_{i=1}^NI(G(x_i) \not=y_i) \leq \frac{1}{N}\sum_{i=1}^N exp(-y_if(x_i))=\prod_mZ_m$

Adaboost可以由前向分布算法推导出

  • 前向分布算法是一种逐步优化的算法,通过逐步地添加弱学习器来改进当前的模型。每次添加的模型都能够在当前模型的基础上,减少训练误差。
  • AdaBoost是一个集成学习方法,尤其是通过加权平均多个弱学习器(通常是决策树)来提高分类精度。AdaBoost通过调整训练样本的权重,逐步强调那些被前一轮弱学习器误分类的样本,使得后续弱学习器更加关注这些难以分类的样本。

前向分布算法:

  1. 初始化$f_0(x)$

  2. 对$m=1,2,…,M$

    极小化损失函数$(\beta_m,\gamma_m)=\underset {\beta,\gamma}{argmin} \sum_{i=1}^NL(y_i,f_{m-1}(x_i)+\beta b(x_i;\gamma))$得到参数$\beta_m,\gamma_m$

    更新加法模型$f_m(x)=f_{m-1}(x)+\beta_mb(x_;\gamma_m)$

  3. 得到假发模型$f(x)=f_M(x)=\sum_{m=1}^M\beta_mb(x_;\gamma_m)$

前向分布算法将同时求解$m=1$到M的所有参数$\beta_m,\gamma_m$的优化问题简化为逐次求解各个参数$\beta_m,\gamma_m$的优化问题。

2.Gradient Boosting Decision Tree 梯度提升树

基于梯度提升的思想,结合多个弱学习器(通常是决策树)来形成一个强学习器。该算法通过迭代地训练多个决策树,每棵树都试图纠正前一棵树的错误,以提高整体预测精度。

(1)提升树

提升树利用加法模型和前向分布算法。以决策树为基函数的提升方法称为提升树。分类问题,决策树是二叉分类树;回归问题,是二叉回归树。提升树模型可以表示为决策树的加法模型:$f_M(x)=\sum_{m=1}^MT(x;\Theta_m)$

其中$T(x;\theta_m)$表示决策树,$\theta_m$为决策树的参数

通过经验风险极小化确定下一棵决策树的参数$\widehat{\Theta}m=\underset{\Theta_m}{argmin}\sum{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\Theta_m))$

回归问题的提升树算法:

训练数据集$T={(x_1,y_1),(x_2,y_2),..,(x_N,y_N)}$,其中$x_i\in R^n,y_i\in Y\subset R$。将输入空间$X$划分为$J$个互不相交的区域$R_1,R_2,…,R_J$,并且在每个区域上确定输出的常量$c_j$,那么树可以表示为$T(x;\Theta)=\sum_{j=1}^Jc_jI(x\in R_j)$。其中参数$\Theta={(R_1,c_1),..,(R_J,c_J)}$表示树的区域划分和各区域上的常数。$J$是回归树的复杂度即叶节点个数。

  1. 初始化$f_0(x)$

  2. 对$m=1,2,…,M$

    计算残差:$r_{mi}=y_i-f_{m-1}(x_i)$

    拟合**残差$r_{mi}$**学习一个回归树$T(x;\Theta_m)$

    更新$f_m(x)=f_{m-1}(x)+T(x;\Theta_m)$

  3. 得到回归问题提升树$f_M(x)=\sum_{m=1}^MT(x;\Theta_m)$

(2)梯度提升树

提升树算法中,当损失函数是平方损失和指数损失时,优化较简单。但对于一般的损失函数,每一步的优化往往不容易。因此,Freidman提出了梯度提升算法。这是利用最速下降法的近似方法,关键是利用损失函数的负梯度在当前模型的值$-\big[\frac{\partial L(y,f(x_i))}{\partial f(x_i)}\big]{f(x)=f{m-1}(x)}$作为回归问题提升树算法中的残差的近似值,拟合回归树。

算法:

  1. 初始化$f_0(x)=\underset{c}{\arg\min}\sum_{i=1}^{N}L(y_i,c)$

  2. 对$m=1,2,…,M$

    计算$r_{mi}=-\big[\frac{\partial L(y,f(x_i))}{\partial f(x_i)}\big]{f(x)=f{m-1}(x)}$

    对$r_{mi}$拟合一个回归树,得到第m颗树的叶节点区域$R_{mj}$

    对$j=1,2…,J$计算$c_{mj}=\underset{c}{\arg\min}\sum_{x_i\in R_{m,j}}L(y_i,f_{m-1}(x_i)+c)$

    更新$f_m(x)=f_{m-1}(x)+\sum_{j=1}^Jc_{mj}I(x\in R_{mj})$

  3. 得到回归树$\widehat{f}(x)=f_M(x)=\sum_{m=1}^M\sum_{j=1}^Jc_{mj}I(x\in R_{mj})$

3.AdaBoost VS GBDT

  • AdaBoost在早期阶段会快速提升模型性能,因为每棵树都在纠正前面的错误分类样本。但随着树的数量增加,可能会出现过拟合的情况。

    基于指数损失

    适合样本数不太多或噪声不大的情况

  • GBDT的收敛速度通常比AdaBoost慢,因为它是通过梯度信息优化损失函数,逐步拟合残差。每棵树的目标是减少整体模型的误差,因此性能较稳定,不易过拟合,对噪声的鲁棒性比较好。可以通过设置较小的学习率降低过拟合的风险,但这需要更多的树来达到相同的性能水平。

    可以自定义损失函数,常用对数损失、指数损失

    适用于各种类型的数据,但更容易过拟合。

    计算开销大,特别是在参数调整和模型训练上。

image-20250330112834834

注:用时4m33s

AdaBoost

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
# 创建一个决策树弱分类器
base_estimator = DecisionTreeClassifier(max_depth=1)
# 创建AdaBoost分类器
ada_boost = AdaBoostClassifier(base_estimator=base_estimator,
n_estimators=50, #迭代次数/弱分类器数量
learning_rate=1.0, #较低的学习率会减少过拟合,但可能需要更多的弱分类器
algorithm='SAMME.R',#SAMME.R(Real AdaBoost)是一个改进版本,通常效果更好,适用于分类问题。SAMME 是传统的算法版本。
loss='exponential')#定义误差度量方式

# 训练模型
ada_boost.fit(X_train, y_train)
# 预测
y_pred = ada_boost.predict(X_test)

GBDT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.ensemble import GradientBoostingClassifier
# 创建GradientBoosting分类器
gb_classifier = GradientBoostingClassifier(n_estimators=100,
learning_rate=0.1,
max_depth=3, #每个弱分类器的最大深度,默认3,更深的树会增加模型复杂度,可能导致过拟合
random_state=42,
min_sample_split=2,#在分裂内部节点时,要求每个节点上的最小样本数。默认是 2。
min_samples_leaf=1,# 每个叶子节点上的最小样本数,防止过拟合。默认值是 1。
max_features='auto')#每棵树可以使用的最大特征数。可以通过选择合适的特征数量来减少过拟合。默认是 'auto',即使用所有特征。
# 训练模型
gb_classifier.fit(X_train, y_train)
# 预测
y_pred = gb_classifier.predict(X_test)

三、Stacking(堆叠泛化)

通过训练一个新的模型来结合多个基分类器预测结果。在 stacking 中,首先训练多个基分类器,然后将这些基分类器的预测结果作为新的输入,来训练一个新的分类器(元分类器Meta Classifier),以得到一个最终的输出。

优点:结合多个不同类型的分类器,充分发挥每个模型的优势。

缺点:相对复杂,需要训练多个基分类器并且还需要训练元分类器。计算成本较高,且容易出现过拟合,尤其是在元分类器选择不当时。

四、Voting(投票法)

Voting 是集成学习中最简单的一种方法,适用于分类任务。它通过组合多个基分类器的预测结果来做出最终决策,常见的投票方式有“多数投票”和“加权投票”。在分类问题中,多个基分类器对同一个样本进行预测,最后根据所有分类器的预测结果进行投票,选出票数最多的类别。如果采用加权投票,每个基分类器的投票会根据其性能给予不同的权重。

优点:实现简单、易于理解。对异常值和噪声有较好的容忍度。

缺点:当基分类器性能差时,投票法的效果可能不好。无法利用基分类器之间的关联信息。

五、Blending

Blending 是一种类似于 stacking 的集成方法,区别在于,它通过将基分类器的输出分为训练集和验证集来训练元分类器。

总结

集成分类器的构建方法有很多,每种方法都有其独特的优势和适用场景。在实际应用中,选择适当的集成方法取决于问题的具体性质、数据的特征以及模型的复杂度。以下是每种方法的适用情况:

  • Bagging:适用于基分类器容易过拟合的情况,如决策树。
  • Boosting:适用于数据存在较多的噪声或模型需要高精度的场景。
  • Stacking:适用于需要结合多种不同类型分类器的场景,尤其是复杂数据问题。
  • Voting:适用于基分类器性能差异不大的情况,且需要快速实现。
  • Blending:适用于需要较快实现集成的场景,但可能不如 stacking 稳定。

集成学习方法(Bagging、Boosting、Stacking)
http://lemonjiang626.github.io/2025/07/12/集成学习方法(Bagging、Boosting、Stacking)/
作者
lemonjiang
发布于
2025年7月12日
许可协议