点击获取AI摘要

集成学习

1. 集成学习 (Ensemble Learning)

集成学习(Ensemble Learning)是一种机器学习范式,其核心思想是 组合多个学习器 (Individual Learners) 来完成学习任务。与单个学习器相比,集成学习通常能够获得比单一最优学习器更好的泛化性能。

  • 核心思想: 通过将多个弱学习器(Weak Learners)组合起来,可以形成一个强学习器(Strong Learner)。
  • 为什么有效: 集成学习能够从不同角度学习数据,通过结合多个模型的预测结果来降低整体误差。具体来说:
    • 统计: 当学习任务的真实模型复杂,单个模型可能因样本不足而陷入局部最优。集成学习在搜索空间中可能找到更接近全局最优的解。
    • 计算: 某些学习算法可能因计算限制而无法获得最优解。集成学习通过组合多个次优解来逼近最优。
    • 表示: 真实任务可能非常复杂,无法通过一个简单的模型来准确描述。集成学习可以通过组合多个模型来表达更复杂的函数关系。
  • 关键点: 集成学习要求个体学习器好而不同
    • “好”: 个体学习器自身的性能不能太差,至少不能低于随机猜测的水平。
    • “不同”: 个体学习器之间应该具有差异性,即预测结果不应高度相关。差异性越大,集成后效果越好。

1.1 集成学习的类型

根据个体学习器的生成方式,目前的集成学习方法大致可以分为两大类:

  1. 并行集成方法 (Parallel Ensemble Methods):
    • 个体学习器之间不存在强依赖关系,可以同时生成。
    • 代表:Bagging (Bootstrap Aggregating) 及其变种 随机森林 (Random Forest)
    • 主要用于降低方差 (Variance),提高模型稳定性。
  2. 串行集成方法 (Sequential Ensemble Methods):
    • 个体学习器之间存在强依赖关系,必须串行生成。后一个学习器需要根据前一个学习器的表现进行调整(通常是关注前一个学习器预测错误的样本或难以预测的区域)。
    • 代表:Boosting 及其变种 AdaBoost (Adaptive Boosting)Gradient Boosting (梯度提升) (GBDT, XGBoost, LightGBM 等)。
    • 主要用于降低偏差 (Bias),提高模型精度。

1.2 结合策略 (Combining Strategy)

在生成个体学习器后,如何将它们的预测结果进行组合以获得最终的集成结果?常用的结合策略包括:

  • 平均法 (Averaging):

    • 对于回归任务,简单平均 (Simple Averaging):

      H(x)=1Ti=1Thi(x)H(x) = \frac{1}{T} \sum_{i=1}^{T} h_i(x)

    • 加权平均 (Weighted Averaging):

      H(x)=i=1Twihi(x)s.t.i=1Twi=1,wi0H(x) = \sum_{i=1}^{T} w_i h_i(x) \quad \text{s.t.} \quad \sum_{i=1}^{T} w_i = 1, w_i \ge 0

      通常个体学习器性能越好,权重越大。

  • 投票法 (Voting):

    • 对于分类任务。

    • 绝对多数投票 (Majority Voting): 投某一类票数超过总票数一半,预测为该类;否则拒绝预测(或交给其他方法)。

      H(x)={cjif i=1TI(hi(x)=cj)>0.5k=1N1rejectotherwiseH(x) = \begin{cases} c_j & \text{if } \sum_{i=1}^{T} \mathbb{I}(h_i(x) = c_j) > 0.5 \sum_{k=1}^{N} 1 \\ \text{reject} & \text{otherwise} \end{cases}

      其中 I()\mathbb{I}(\cdot) 是指示函数。

    • 相对多数投票 (Plurality Voting): 预测为得票最多的类。

      H(x)=argmaxcji=1TI(hi(x)=cj)H(x) = \arg \max_{c_j} \sum_{i=1}^{T} \mathbb{I}(h_i(x) = c_j)

    • 加权投票 (Weighted Voting):

      H(x)=argmaxcji=1TwiI(hi(x)=cj)s.t.i=1Twi=1,wi0H(x) = \arg \max_{c_j} \sum_{i=1}^{T} w_i \mathbb{I}(h_i(x) = c_j) \quad \text{s.t.} \quad \sum_{i=1}^{T} w_i = 1, w_i \ge 0

  • 学习法 (Learning):

    • 通过一个独立的学习器(称为元学习器 (Meta-learner)堆叠器 (Stacker))来结合个体学习器的预测结果。
    • 代表:Stacking。先训练个体学习器,然后将个体学习器的输出作为新的特征,用于训练元学习器。

2. 基于树模型的集成方法 (Tree-based Ensemble Methods)

决策树是集成学习中最常用的个体学习器之一,因为它非线性、可以处理多种数据类型且易于实现。

2.1 Bagging 与随机森林 (Random Forest)

2.1.1 Bagging (Bootstrap Aggregating)

  • 原理: 通过 自助采样 (Bootstrap Sampling) 生成不同的数据集,并在每个数据集上独立训练一个决策树(或其他学习器)。
  • 自助采样: 从原始包含 m 个样本的数据集 D 中,有放回地随机抽取 m 个样本,构成新的数据集 D’。重复此过程 T 次,得到 T 个不同的训练集 D₁, D₂, …, Dₜ。
  • 个体学习器训练: 在每个数据集 Dᵢ 上独立训练一个决策树模型 hᵢ。这些树之间是并行的。个体决策树通常不进行剪枝或只进行少量预剪枝,因为Bagging的目标是通过组合降低方差,即使个体树的方差较高。
  • 预测:
    • 分类: 对新样本进行预测时,所有树独立给出预测结果,最后通过投票法(如相对多数投票)决定最终类别。
    • 回归: 对新样本进行预测时,所有树独立给出预测结果,最后通过简单平均法求平均值作为最终预测结果。
  • 优点:
    • 有效地降低方差,对噪声数据不那么敏感。
    • 个体学习器之间无依赖,可并行计算。
    • 自助采样会产生一部分未被采样的样本,称为 包外样本 (Out-of-Bag, OOB) 样本,可以用于模型的无偏估计,无需额外的验证集。平均约有 36.8% (11/m)me10.368(1 - 1/m)^m \approx e^{-1} \approx 0.368 的原始样本不会出现在某个自助采样集中。
  • 缺点:
    • 不能降低个体学习器的偏差
    • 模型的可解释性变差。

2.1.2 随机森林 (Random Forest, RF)

  • 原理: 是 Bagging 的一个扩展。它在 Bagging 的基础上,在训练每个决策树时,在每个节点进行分裂时引入了特征随机性
  • 特征随机性: 对于节点上的数据集,不再考虑所有的特征来选择最优分裂属性,而是从当前节点的特征集合中随机抽取一个包含 k 个特征的子集,再从这个子集中选择最优特征进行分裂。
  • 参数 k: 通常推荐 k = sqrt(d) (d为特征总数) 用于分类任务,k = dk = d/3 用于回归任务。Scikit-learn 中 max_features 参数控制 k
  • 为何引入特征随机性? Bagging 中,如果数据中存在一个或几个非常强的特征,那么几乎所有生成的树在根节点都会使用这些强特征进行分裂,导致生成的树之间高度相关,限制了方差的进一步降低。特征随机性强制每棵树使用不同的特征子集,增加了树之间的差异性,从而进一步降低了方差。
  • 随机森林的步骤:
    1. 从原始数据集 D 中通过自助采样生成 T 个训练集 D₁, …, Dₜ
    2. 对于每个训练集 Dᵢ,训练一棵决策树 hᵢ。在训练过程中,对于树的每个节点,从所有特征中随机选择 max_features 个特征子集,并仅基于这些子集选择最优分裂点。树的生长通常是完全分裂的(不进行剪枝),或者只进行少量预剪枝。
    3. 集成 T 棵树的预测结果(分类投票,回归平均)。

随机森林工作流程

  • 优点:
    • 相比 Bagging,由于引入特征随机性,进一步降低了模型方差,泛化能力更强。
    • 不容易过拟合(个体树的随机性使得它们不过于依赖训练数据的特定模式,且整体通过集成降低方差)。
    • 能够处理高维数据。
    • 可以自然地计算特征重要性 (Feature Importance):通过某个特征在所有树中作为分裂特征时,平均带来的不纯度减少总量来衡量。
    • OOB 样本可以用于内部评估,提供了一个无需额外验证集的性能估计。
  • 缺点:
    • 模型可解释性差。
    • 训练时间和预测时间随树的数量增加而增加。
    • 在某些数据集上,尤其是 Boosting 方法能够捕捉复杂相互作用的情况下,表现可能不如 Boosting 方法。

特征重要性计算 (Feature Importance Calculation)
随机森林能够计算特征重要性,这通常基于某个特征在森林中所有树中作为分裂特征时带来的平均不纯度减少(如使用 Gini 作为 criterion 时的 Gini 不纯度减少)。我们将变量重要性评分表示为 VIMVIM,对于基于 Gini 指数的,记为 VIM(Gini)VIM^{(Gini)}
假设数据集有 cc 个特征 X1,X2,X3,...,XcX_1, X_2, X_3, ..., X_c。现在要计算每个特征 XjX_jGiniGini 指数评分 VIMj(Gini)VIM_j^{(Gini)},即特征 XjX_j 在随机森林所有决策树中节点分裂不纯度的平均改变量。
如果在决策树 ii 中,特征 XjX_j 出现的节点集合是 MM,那么 XjX_j 在第 ii 棵树中的重要性为:

VIMij(Gini)=mMVIMjm(Gini)VIM_{ij}^{(Gini)} = \sum_{m \in M} VIM_{jm}^{(Gini)}

其中,VIMjm(Gini)VIM_{jm}^{(Gini)} 是特征 XjX_j 在树 ii 的节点 mm 处分裂时带来的 Gini 不纯度减少量。
假设随机森林 RFRF 中共有 nn 棵树,那么特征 XjX_j 在整个随机森林中的原始总重要性为:

VIMj(Gini)=i=1nVIMij(Gini)VIM_j^{(Gini)} = \sum_{i=1}^{n} VIM_{ij}^{(Gini)}

(注意:Scikit-learn 实现中通常是计算平均不纯度减少,可能是在累加前或累加后除以树的数量 nn)。
最后,把所有特征求得的原始重要性评分做一个归一化处理,得到最终的特征重要性得分:

VIMj=VIMj(Gini)k=1cVIMk(Gini)VIM_j = \frac{VIM_j^{(Gini)}}{\sum_{k=1}^{c} VIM_k^{(Gini)}}

Scikit-learn 中的 random_state.feature_importances_ 属性提供了这个归一化后的得分数组。这个得分越高,表示该特征在模型预测中起到的作用越大。

sklearn中的参数

参数/属性 描述 默认值 类型/选项 重要性级别
n_estimators 森林中树的数量。 数量越多通常模型越稳健,但也增加计算开销。 100 integer, optional
criterion 衡量分裂质量的函数。 常用的有 “gini” (基尼不纯度) 和 “entropy” (信息增益)。 “gini” string, optional (“gini”, “entropy”)
max_depth 树的最大深度。 限制深度有助于防止过拟合。None 表示树会完全生长直到叶子纯净或达到 min_samples_split 的限制。RF通常不限制深度以降低偏差,但可能会引入一些方差,通过集成解决。 None integer or None, optional 中/低
min_samples_split 分裂内部节点所需的最小样本数。 数量太小可能导致过拟合。 2 int or float, optional
min_samples_leaf 叶子节点所需的最小样本数。 数量太小可能导致过拟合,数量太大有平滑模型作用。特别影响回归任务。 1 int or float, optional
max_features 寻找最佳分裂时考虑的特征数量。 控制特征随机性。autosqrt 通常指 sqrt(n_features)log2log2(n_features)Nonen_features。 这是 RF 区别于 Bagging 的关键参数。 “auto” int, float, string or None, optional
bootstrap 建树时是否采用有放回抽样 (bootstrap)。 True 开启随机性(Bagging的核心),False 使用整个数据集。RF 通常使用 True True boolean, optional
oob_score 是否使用外包样本 (OOB) 评估模型的泛化准确性。 需要 bootstrap=True 才能计算。提供无需额外验证集的性能评估。 False boolean, optional
n_jobs 并行计算使用的CPU数量。 -1 表示使用所有可用的处理器。 None int or None, optional 实用
random_state 随机状态/种子。 设置后可确保自助采样、特征随机性等的可复现性。 None int, RandomState instance or None, optional 实用
feature_importances_ [属性] 特征重要性系数。 拟合后可用此属性查看每个特征的重要性得分。基于特征在树中分裂节点时平均带来的不纯度减少计算并归一化。 N/A array of shape = [n_features_] N/A
oob_score_ [属性] 外包样本评估分数。oob_score=Truebootstrap=True 时可用,存储计算出的 OOB 分数。 N/A float N/A
classes_ [属性] 模型知道的类别标签。 对于分类问题,这个属性存储了训练集中出现的唯一类别。 N/A array of shape = [n_classes_] or list of arrays N/A
n_features_ [属性] 训练时使用的特征数量。 N/A int N/A
n_classes_ [属性] 类别数量。 对于多分类,指类别的总数。 N/A int or list N/A

2.2 Boosting

  • 原理: 是一种迭代的集成方法,个体学习器之间是串行的。每次迭代都会根据前一次迭代的预测结果来调整样本权重(如 AdaBoost)或学习前一轮模型的残差或负梯度(如 GBDT),使得新的学习器更关注之前被错误预测的样本或难以预测的区域。
  • 核心思想: 每一棵树都尝试去弥补前面所有树的不足。
  • 常用个体学习器: 弱学习器,尤其是决策树桩 (Decision Stump)(深度为1的决策树)或非常浅的决策树。这是因为 Boosting 主要目的是降低偏差,而弱学习器本身偏差高方差低,通过Boosting组合后,偏差可以降低,同时保持较低的方差。使用浅树也能显著提高模型的泛化能力和训练速度。

2.2.1 AdaBoost (Adaptive Boosting)

  • 原理: 通过不断修改样本的权重来训练一系列弱分类器。它会给错误分类的样本更高的权重,使得后续的弱分类器更关注这些样本。

  • 过程:

    1. 初始化所有样本的权重相等,设为 1/m1/m,其中 m 是样本总数。

    2. 迭代 T 次,训练 T 个弱分类器 h₁, …, hₜ:
      a. 使用当前样本权重分布 DtD_t 训练弱分类器 ht(x)h_t(x)
      b. 计算当前弱分类器 hth_t 在加权训练数据集上的分类误差率 ϵt\epsilon_t

      ϵt=P(ht(xi)yi)=i=1mwi(t)I(ht(xi)yi)\epsilon_t = P(h_t(x_i) \neq y_i) = \sum_{i=1}^{m} w_i^{(t)} \mathbb{I}(h_t(x_i) \neq y_i)

      c. 计算当前弱分类器 hth_t权重 αt\alpha_t(该分类器在最终集成结果中的重要性):

      αt=12ln(1ϵtϵt) \alpha_t = \frac{1}{2} \ln \left( \frac{1 - \epsilon_t}{\epsilon_t} \right)

      这里的 ϵt\epsilon_t 必须小于 0.5(弱分类器性能必须好于随机猜测),否则算法停止。 ϵt\epsilon_t 越小,αt\alpha_t 越大。

      d. 更新样本权重: 增加被 hth_t 错误分类的样本的权重,减少被正确分类的样本的权重。

      wi(t+1)=wi(t)exp(αtyiht(xi))w_i^{(t+1)} = w_i^{(t)} \exp(-\alpha_t y_i h_t(x_i))

      其中 yiy_i 是真实标签(对于二分类通常取 +1 或 -1),ht(xi)h_t(x_i) 是预测结果。如果预测正确, yiht(xi)>0y_i h_t(x_i) > 0,权重减小;如果预测错误,yiht(xi)<0y_i h_t(x_i) < 0,权重增加。

      e. 归一化样本权重:w(t+1)w^{(t+1)} 归一化,使其总和为 1,得到新的样本权重分布 Dt+1D_{t+1}

    3. 最终的强分类器由所有弱分类器加权组合而成:

      H(x)=sign(t=1Tαtht(x))H(x) = \text{sign} \left( \sum_{t=1}^{T} \alpha_t h_t(x) \right)

      (对于分类任务,通常是加权投票;对于回归任务,AdaBoost.R2 等有不同策略)

  • 优点:

    • 算法简单,易于实现。
    • 分类精度高,可以提高弱分类器的性能。
    • 无需预知弱学习器性能,只需保证性能优于随机猜测。
  • 缺点:

    • 对异常值和噪声数据比较敏感(因为会给误分类样本过高的权重)。
    • 训练是串行的,难以并行处理。
    • 主要用于二分类问题,扩展到多分类需要一些修改。

2.2.2 梯度提升 (Gradient Boosting Machines, GBM)

  • 原理: 通过构建一系列决策树来最小化某个损失函数的负梯度。每一棵树不是直接预测目标变量或残差,而是预测当前模型在训练数据上的负梯度,然后将新树的预测结果(乘以学习率)叠加到现有模型上,沿着损失函数梯度的反方向进行优化。

  • 过程 (以回归为例,使用均方误差损失 L(y,F)=12(yF)2L(y, F) = \frac{1}{2}(y-F)^2):

    1. 初始化一个简单的模型,通常是预测使损失函数最小的常数(例如,对于 MSE 是所有样本的平均目标值) f0(x)f_0(x)

    2. 迭代 T 次:
      a. 对于每个样本 ii,计算当前模型 ft1(xi)f_{t-1}(x_i) 在该样本上的损失函数的负梯度。这被称为伪残差 (Pseudo-residuals)

      rit=[L(yi,F(xi))F(xi)]F(x)=ft1(x)r_{it} = - \left[ \frac{\partial L(y_i, F(x_i))}{\partial F(x_i)} \right]_{F(x)=f_{t-1}(x)}

      对于 MSE 损失 L(y,F)=12(yF)2L(y, F) = \frac{1}{2}(y-F)^2,负梯度就是 yift1(xi)y_i - f_{t-1}(x_i),这恰好是残差。对于其他损失函数,负梯度是残差的一种推广。

      b. 训练一棵新的决策树 ht(x)h_t(x) 来拟合这些伪残差 ritr_{it}

      c. 找到最佳步长 γt\gamma_t 来更新模型(在 GBDT 中通常简化为学习率 η\eta):

      ft(x)=ft1(x)+ηht(x)f_t(x) = f_{t-1}(x) + \eta h_t(x)

      这里的 η\eta 就是学习率 (Learning Rate)。

    3. 最终模型是所有树的加权求和 (这里权重是学习率):

      F(x)=f0(x)+t=1Tηht(x)F(x) = f_0(x) + \sum_{t=1}^{T} \eta h_t(x)

  • 损失函数 (Loss Function): Gradient Boosting 可以使用各种可微的损失函数,例如回归中的均方误差 (MSE)、平均绝对误差 (MAE),分类中的对数损失 (Log Loss, 即 scikit-learn 中的 ‘deviance’)。选择合适的损失函数对模型性能至关重要。

  • 学习率 (Learning Rate, η\eta): 是一个重要的超参数,介于 0 和 1 之间。它缩放了每棵树的贡献。较小的学习率意味着每棵树的贡献较小,需要更多棵树才能达到相同的效果,但这通常能带来更好的泛化能力和鲁棒性。这是一种收缩 (Shrinkage) 技术。学习率和 n_estimators 之间存在一个重要的权衡:较小的学习率通常需要更大的 n_estimators 来弥补。

  • 个体学习器: 通常使用回归树,即使是分类问题(因为它们拟合的是伪残差或负梯度,这些是数值)。树的深度通常也比较浅 (e.g., max_depth=3-6),以保证个体学习器是弱学习器,从而通过 Boosting 降低偏差。

  • 随机梯度提升 (Stochastic Gradient Boosting): 通过设置 subsample 参数小于 1.0,在训练每棵树时随机抽取一部分样本(不放回抽样),可以进一步引入随机性,减少方差,提高模型的鲁棒性。这借鉴了 Bagging 的思想。

  • 早期停止 (Early Stopping): 由于 Boosting 容易在迭代次数过多时过拟合,通常会使用一个验证集并在验证集性能不再提升时提前停止训练。这通过 validation_fraction, n_iter_no_change, tol 等参数来控制。

  • 常见变体:

    • GBDT (Gradient Boosting Decision Tree): 指使用决策树作为个体学习器的 Gradient Boosting。
    • XGBoost (Extreme Gradient Boosting): GBDT 的优化版本,加入了正则化项(树结构和叶子节点权重)、并行处理(在特征和数据级别)、缺失值处理、剪枝策略等改进,速度和性能通常更好。
    • LightGBM (Light Gradient Boosting Machine): 微软开发的 GBDT 变体,使用基于梯度的单边采样 (GOSS) 和互斥特征捆绑 (EFB) 等技术,速度非常快,适合处理大规模数据。
    • CatBoost: Yandex 开发的 GBDT 变体,对类别特征有特殊处理,并采用有序提升以减少过拟合。
  • 优点:

    • 预测精度非常高,在许多比赛中表现优异。
    • 可以灵活选择损失函数。
    • 通过引入 subsample 和浅树可以增加鲁棒性。
    • 早期停止是一种有效的正则化手段。
  • 缺点:

    • 训练过程是串行的,难以完全并行化(树之间有依赖)。
    • 对超参数比较敏感,需要仔细调参。
    • 容易过拟合(尤其是树的数量过多、学习率过大或树深度过深时), Early Stopping 是必要的。

sklearn.ensemble.GradientBoostingClassifier 参数解释

参数/属性 描述 默认值 类型/选项 重要性级别
loss 需要优化的损失函数。对于分类任务,‘deviance’ (即对数损失 logloss) 更常用,‘exponential’ 对应 AdaBoost 算法。 ‘deviance’ {‘deviance’, ‘exponential’}, optional
learning_rate 学习率 (shrinkage)。控制每个弱学习器的贡献大小。较小的值需要更多 n_estimators。在 learning_raten_estimators 之间存在权衡。 0.1 float, optional
n_estimators Boosting 迭代次数,即弱学习器(树)的数量。 Gradient Boosting 通常对过拟合有鲁棒性,但数量过多仍可能过拟合。一个较大的数通常意味着更好的性能,但也增加计算开销。需要配合 learning_rate 和早期停止进行调优。 100 int, optional
subsample 用于训练基学习器的样本采样比例。 小于 1.0 则等同于随机梯度提升 (Stochastic Gradient Boosting)。如果小于 1 则会减少方差,增加偏差,提高鲁棒性。 1.0 float, optional
criterion 衡量分裂质量的函数。 这是与基学习器决策树相关的参数。'friedman_mse' 是一个常用的选项,它在均方误差基础上考虑了分裂点的改进。 ‘friedman_mse’ string, optional
min_samples_split 分裂内部节点所需的最小样本数。 可以是整数(绝对数量)或浮点数(比例)。 2 int or float, optional
min_samples_leaf 叶子节点所需的最小样本数。 可以是整数(绝对数量)或浮点数(比例)。有平滑模型的作用,特别是回归任务。 1 int or float, optional
min_weight_fraction_leaf 叶子节点所需的样本总权重的最小分数。 0.0 float, optional
max_depth 单个回归树的最大深度。 需要进行调参来获得更好的性能。通常设置一个较小的值(例如 3-6)来构建弱学习器。 3 integer, optional
min_impurity_decrease 节点分裂的最小不纯度减少量。 如果节点分裂带来的不纯度减少大于或等于该值,节点才会分裂。 0.0 float, optional
min_impurity_split 建树过程中早起停止的阈值。 如果节点的不纯度大于该值会继续分裂,否则停止,成为叶子节点。已废弃,后续版本将被 min_impurity_decrease 参数代替。 1e-7 float, optional (deprecated since 0.19) N/A
init 用来模型初始化的学习器对象或 ‘zero’。 可以提供已 fit 或 predict 的对象。如果是 ‘zero’ 则初始预测为 0。 None estimator or ‘zero’, optional
random_state 随机状态/种子。 控制自助采样 (bootstrap) 和特征选择的随机性,用于结果的可复现性。 None int, RandomState instance or None, optional 实用
max_features 寻找最佳分裂时考虑的特征数量。 控制特征子集的随机性。可以是整数、浮点数、字符串 (‘auto’, ‘sqrt’, ‘log2’) 或 None。‘auto’ 和 ‘sqrt’ 都表示 sqrt(n_features),‘log2’ 表示 log2(n_features),None 表示 n_features ‘auto’ int, float, string or None, optional
verbose 控制训练过程的输出详细程度。 0 表示无输出,1-3 表示不同详细程度的输出。 0 int, optional 实用
max_leaf_nodes 以最优的方式构建树,限制叶子节点的数量。 如果是 None 则对叶子节点的数量没有限制。可以替代 max_depth None int or None, optional
warm_start 布尔值。 如果设置为 True,将重用上一次调用的解来学习并加入更多的学习器到集成算法中,可以用于增加已训练模型的树数量,无需从头训练。 False bool, optional 实用
presort 在寻找最佳分裂时是否预排序数据。 自动模式对稠密数据进行预排序,稀疏数据不排序。 (已废弃) ‘auto’ bool or ‘auto’, optional (deprecated since 0.22) N/A
validation_fraction 用于早期停止的验证集比例。 如果设置了,模型会在每次迭代后在一个随机划分的验证集上评估性能。 0.1 float, optional 高 (用于Early Stopping)
n_iter_no_change 在验证分数不再提高时采用 early stopping 的迭代次数。 如果设置为整数,当连续 n_iter_no_change 次迭代验证分数(在 validation_fraction 定义的验证集上)没有超过 tol 定义的阈值时,则停止训练。默认 None 不考虑 early stopping。 None int or None, optional 高 (用于Early Stopping)
tol early stopping 的容差 (tolerance)。 在 early stopping 启用时,经过 n_iter_no_change 步迭代的提升都没有超过 tol 时,则停止训练。 1e-4 float, optional 高 (用于Early Stopping)
feature_importances_ [属性] 特征重要性系数。 拟合后可用此属性查看每个特征的重要性得分。基于特征在树中分裂节点时平均带来的不纯度减少计算并归一化。 N/A array of shape = [n_features_] N/A

补充说明:Early Stopping (早期停止)

在 GBDT 中,n_estimators 是一个非常关键的参数,迭代次数越多,模型复杂度越高,越容易过拟合。为了平衡性能和过拟合,并避免手动尝试大量 n_estimators 值,常常使用早期停止技术。

启用早期停止需要:

  1. 设置 n_iter_no_change 为一个整数。
  2. 可选地设置 validation_fraction 来指定用于评估的验证集比例(如果不设置,会从训练集中自动划分)。
  3. 可选地设置 tol 来指定判断性能是否提高的最小阈值。

当在验证集上的性能连续 n_iter_no_change 次迭代没有提升超过 tol 时,训练会自动停止,而不是跑到 n_estimators 设定的最大值。这是一种有效的正则化手段,也能节省训练时间。

2.3 Bagging vs. Boosting 总结比较

特征 Bagging (e.g., Random Forest) Boosting (e.g., AdaBoost, GBDT)
个体学习器关系 并行,无依赖,独立生成 串行,有依赖,顺序生成
主要目标 降低方差 (Variance),提高稳定性 降低偏差 (Bias),提高精度
如何实现 重新采样数据 (Bootstrap),组合多个独立模型 调整样本权重/拟合残差/负梯度,迭代训练关注错误样本/区域的模型
个体学习器 通常使用强学习器(如剪枝较少的深树),但在RF中通过特征随机性增加差异 通常使用弱学习器(如决策树桩或浅层树)
训练速度 可并行,训练速度快 串行,训练速度慢(相较于 Bagging)
对噪声/异常值 鲁棒性较好 敏感 (尤其是 AdaBoost,GBDT 通过 Subsample 可改善)
解释性 较差 更差
典型算法 Bagging Classifier/Regressor, Random Forest AdaBoost, Gradient Boosting, XGBoost, LightGBM, CatBoost

2.4 Scikit-learn 实现示例 (集成学习)

继续使用 Iris 数据集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 导入所需的集成模型
from sklearn.ensemble import BaggingClassifier, RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.model_selection import train_test_split # 如果之前没有导入和分割数据,需要运行这几行
from sklearn.metrics import accuracy_score, classification_report
from sklearn.datasets import load_iris

# 加载数据集 (如果之前没有加载)
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
target_names = iris.target_names

# 分割数据集 (如果之前没有分割)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)


print("\n--- 集成学习模型示例 ---")

# --- 8.4.1 Bagging Classifier ---
print("\nBagging Classifier:")
# BaggingClassifier 默认使用 DecisionTreeClassifier 作为基学习器
# n_estimators: 基学习器的数量
bagging_clf = BaggingClassifier(n_estimators=100, random_state=42, n_jobs=-1) # n_jobs=-1 使用所有CPU核心并行训练
bagging_clf.fit(X_train, y_train)
y_pred_bagging = bagging_clf.predict(X_test)
accuracy_bagging = accuracy_score(y_test, y_pred_bagging)
print(f"准确率: {accuracy_bagging:.4f}")
# print("分类报告:\n", classification_report(y_test, y_pred_bagging, target_names=target_names))

# --- 8.4.2 Random Forest Classifier ---
print("\nRandom Forest Classifier:")
# random_state 用于控制bootstrap采样和特征随机性
# n_estimators: 树的数量
# max_features: 控制特征随机性 ('sqrt', 'log2', int, float)
rf_clf = RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1)
rf_clf.fit(X_train, y_train)
y_pred_rf = rf_clf.predict(X_test)
accuracy_rf = accuracy_score(y_test, y_pred_rf)
print(f"准确率: {accuracy_rf:.4f}")
print("特征重要性 (Random Forest):")
# 使用 zip 将特征名和重要性分数对应起来打印
for name, importance in zip(feature_names, rf_clf.feature_importances_):
print(f" {name}: {importance:.4f}")
# print("分类报告:\n", classification_report(y_test, y_pred_rf, target_names=target_names))

# --- 8.4.3 AdaBoost Classifier ---
print("\nAdaBoost Classifier:")
# base_estimator: 基学习器 (默认是决策树桩 DecisionTreeClassifier(max_depth=1))
# n_estimators: 弱学习器的数量
# learning_rate: 控制每个弱学习器的贡献
adaboost_clf = AdaBoostClassifier(n_estimators=50, learning_rate=1.0, random_state=42)
adaboost_clf.fit(X_train, y_train)
y_pred_adaboost = adaboost_clf.predict(X_test)
accuracy_adaboost = accuracy_score(y_test, y_pred_adaboost)
print(f"准确率: {accuracy_adaboost:.4f}")
# print("分类报告:\n", classification_report(y_test, y_pred_adaboost, target_names=target_names))

# --- 8.4.4 Gradient Boosting Classifier ---
print("\nGradient Boosting Classifier:")
# n_estimators: 提升阶段的数量 (树的数量)
# learning_rate: 控制收缩
# max_depth: 个体回归树的深度 (通常较浅)
# Early Stopping 参数示例:validation_fraction, n_iter_no_change, tol
gb_clf = GradientBoostingClassifier(n_estimators=200, # 初始设置多一些树
learning_rate=0.1,
max_depth=3,
random_state=42,
subsample=0.8, # 启用随机梯度提升
validation_fraction=0.1, # 留出10%用于验证
n_iter_no_change=10, # 连续10次迭代验证分数没有提升就停止
tol=0.0001,
verbose=1 # 打印训练过程信息
)
gb_clf.fit(X_train, y_train)
y_pred_gb = gb_clf.predict(X_test)
accuracy_gb = accuracy_score(y_test, y_pred_gb)
print(f"准确率: {accuracy_gb:.4f}")
# 训练停止时的实际树数量可以通过 gb_clf.n_estimators_ 属性查看
print(f"实际训练的树数量: {gb_clf.n_estimators_}")
print("特征重要性 (Gradient Boosting):")
# GradientBoostingClassifier 也有 feature_importances_ 属性
for name, importance in zip(feature_names, gb_clf.feature_importances_):
print(f" {name}: {importance:.4f}")
# print("分类报告:\n", classification_report(y_test, y_pred_gb, target_names=target_names))

2.5 集成方法的调参

集成方法的性能很大程度上依赖于超参数的选择。一些关键参数包括:

  • n_estimators: 集成中个体学习器的数量。数量越多通常性能越好,但计算成本也越高,并且可能导致过拟合(特别是 Boosting)。在 Boosting 中常与 learning_rate 和早期停止配合使用。
  • learning_rate (仅 Boosting): 控制每一步的贡献大小(收缩)。较小的学习率需要更多的 n_estimators,但通常能提高模型鲁棒性和泛化能力。
  • max_depth (个体树深度): 控制个体学习器的复杂度。在 Boosting 中通常设置为较小的值 (e.g., 3-6) 来构建弱学习器。在 RF 中通常设置较大或不限制,依赖特征随机性来降低相关性。
  • max_features: 在 RF 或设置 max_features 的 GBDT 中控制特征随机性。
  • subsample (仅 Bagging/RF/GBDT): 控制样本采样比例。小于 1.0 引入样本随机性,减少方差。
  • 从基学习器继承的参数,如 min_samples_split, min_samples_leaf, min_impurity_decrease 等。
  • 早期停止相关的参数 (仅 GBDT): n_iter_no_change, validation_fraction, tol

调参常用技术:网格搜索 (Grid Search)、随机搜索 (Random Search)、贝叶斯优化等,并结合交叉验证 (Cross-Validation) 来评估参数组合的性能。

3. 小结

决策树作为一种直观且强大的模型,是集成学习中最常用的基学习器之一。通过 Bagging 和 Boosting 这两大主流集成策略,可以有效地提升决策树模型的性能,降低过拟合(Bagging)或提高精度(Boosting)。随机森林是 Bagging 的杰出代表,通过特征随机性进一步增强了性能。Gradient Boosting (及其变体 XGBoost, LightGBM 等) 是 Boosting 方法的代表,在许多复杂任务中取得了最佳效果,通过拟合负梯度进行迭代优化,并可以通过学习率、Early Stopping 和 Subsample 等技术进一步提升性能和鲁棒性。理解这些方法的原理和它们如何结合决策树,对于解决实际问题至关重要。