Py学习  »  机器学习算法

机器学习入门之集成学习

just_sk • 4 年前 • 209 次点击  
阅读 13

机器学习入门之集成学习

概要

集成学习 ensemble learning 是通过构建多个学习器来完成学习任务,在实际应用以及各大竞赛中应用非常广泛。根据学习器的生成方式,集成学习方法大概可以分作两类:

  1. 每一个学习器之间不存在依赖关系,可以并行运行。比如 Bagging 和 Random Forest。
  2. 每一个学习器之间存在依赖关系,必须串行运行,每一轮迭代产生一个学习器。比如 Boosting 算法。

Bagging

Bagging 是借助于 bootstrap 算法来采样。给定包含 N 个样本的数据集,步骤是:

  • 先随机取出一个样本放入采样集中,再把该样本放回原始数据集。
  • 经过 N 次随机采样操作后可以得到包含 N 个样本的采样集。

初始训练集中有的样本在采样集中多次出现,有的则从未出现。一个样本始终不在采样集中出现的概率是 \left(1-\frac{1}{N}\right)^{N}。根据 \lim _{N \rightarrow \infty}\left(1-\frac{1}{N}\right)^{N}=\frac{1}{e} \simeq=0.368,因此初始训练集中约有 63.2% 的样本来训练,剩下的约 36.8% 的样本可用作验证集来对泛化性能进行包外估计。

使用 M 个学习器的 Bagging 的基本流程:

  • 经过 M 轮自助采样,可以得到 M 个包含 N 个训练样本的采样集。
  • 然后基于每个采样集训练出一个基学习器。
  • 最后将这 M 个基学习器进行组合,得到集成模型。

使用 Bagging 学习器进行预测时,分类任务采取简单投票法,取每个基学习器的预测类别的众数;回归任务使用简单平均法,取每个基学习器的预测值的平均。

Bagging 算法可以降低方差,在非剪枝决策树、神经网络等容易受到样本扰动的算法上效果很明显。而 Boosting 算法可以用来降低偏差,它能将一些弱学习器提升为强学习器。因此它在 svm、knn 等不容易受到样本扰动的学习器上效果更为明显。

在 sklearn 中使用 bagging 代码如下,其中 n_estimators 代表使用 500 个决策树学习器进行集成学习,max_samples 代表每个学习器最多 100 个样本,max_features 代表决策树每一个节点最多使用两个特征,oob_score=True 代表使用剩余的 1/3 样本进行评估。

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier

bagging_clf = BaggingClassifier(DecisionTreeClassifier(), n_estimators=500, max_samples=1000, max_features=2,  bootstrap=True, oob_score=True, n_jobs=-1)
bagging_clf.fit(X, y)                            
复制代码

随机森林

随机森林 Random Forest 是 Bagging 的一个演变算法。随机森林对 Bagging 做了一些改进。

  • Bagging 中学习器的多样性来自于样本扰动。样本扰动来自于对初始训练集的随机采样。
  • 随机森林中的学习器的多样性不仅来自样本扰动,还来自属性扰动。这可以大大提高模型的泛化能力。

听着有些抽象,实际上就是在随机森林中,对基决策树的每个结点,先从该结点的属性集合中随机选择一个包含 k 个属性的子集,然后再从这个子集中选择一个最优属性用于划分:

  • 如果 k = n,则基决策树的构建与传统决策树相同。
  • 如果 k = 1,则随机选择一个属性用于划分。
  • 通常建议 k=\log _{2} n

随着树的数量的增加,随机森林可以有效缓解过拟合。因为随着树的数量增加,模型的方差会显著降低。但是树的数量增加并不会纠正偏差,因此随机森林还是会有过拟合。

在 sklearn 中使用随机森林非常简单,注意随机森林拥有 DecisionTreeClassifier 和 BaggingClassifier 的所有参数,比如:

rf_clf2 = RandomForestClassifier(n_estimators=500, max_leaf_nodes=16, max_depth=10, min_samples_split=2, min_samples_leaf=2, max_leaf_nodes=None, oob_score=True, n_jobs=-1)
rf_clf2.fit(X, y)

rf_clf2.oob_score_
复制代码

因为 RandomForestClassifier/RandomForestRegression 在 kaggle/天池这样的比赛用的比较多,下面将一些重要的参数列一下:

  • n_estimators: 子模型的数量,默认为 10。
  • max_features: 节点分裂时参与判断的最大特征数,可以有的取值:
    • int: 特征个数。
    • float: 占所有特征的百分比。
    • auto/sqrt: 所有特征数的开方。
    • log2: 所有特征数的 log2 值。
    • None: 等于所有特征数。
  • max_depth: 如果 max_leaf_nodes 有指定则忽略
    • int: 树的最大深度
    • None: 树会生长到所有叶子都分到一个类,或者某节点所代表的样本数已小于 min_samples_split
  • min_samples_split: 分裂所需的最小样本数,默认为 2。
  • max_leaf_nodes: 最多有多少叶节点,为 None 表示不限制。
  • bootstrap: 时候对样本进行 bootstrap 抽样,默认为 ture,为 false 则各个子模型的样本一致。
  • oob_score: 是否计算袋外得分。

AdaBoost

提升方法(boosting) 是一种常用的统计学习方法。在分类问题中,它通过改变训练样本的权重学习多个分类器,并将这些分类器们进行线性组合来提高分类的能力。提升方法的基本思想是:对于一个复杂任务来说,将多个专家的判断进行适当的综合所得出的判断,要比其中任何一个专家单独的判断要好。用一句古话说就是”三个臭皮匠顶一个诸葛亮“。

boosting 算法的一个大概流程是:

  • 首先从初始训练集训练出一个基学习器。
  • 再根据基学习器的表现对训练样本权重进行调整,使得先前基学习器做错的训练样本在后续受到更多关注。
  • 然后基于调整后的样本分布来训练下一个基学习器。
  • 如此重复,直到基学习器数量达到事先指定的值 M。最终将这 M 个基学习器进行加权组合。

boosting 算法中最著名的是 AdaBoost 算法。AdaBoost 算法有两个核心概念:

  • 每一轮中如何改变训练数据的权值?AdaBoost算法提高那些被前一轮弱分类器错误分类样本的权值,而降低那些被正确分类样本的权值。于是那些没有得到正确分类的数据由于权值的加大而受到后一轮的弱分类器的更大关注。
  • 最后如何将一系列弱分类器组合成一个强分类器?AdaBoost 采用加权多数表决的方法:
    • 加大分类误差率较小的弱分类器的权值,使得它在表决中起较大作用。
    • 减小分类误差率较大的弱分类器的权值,使得它在表决中起较小的作用。

AdaBoost 算法不改变所给的训练数据,而不断改变训练数据权值的分布,使得训练数据在基本分类器的学习中起不同作用。因此 AdaBoost 要求基本学习器能够对特定的数据分布进行学习,这一般是在学习的时候为每个训练样本赋予一个权重。Adaboost 算法的基本公示如下,下面一节做一个详细的介绍。

H(\overrightarrow{\mathbf{x}})=\operatorname{sign}(f(\overrightarrow{\mathbf{x}}))=\operatorname{sign}\left(\sum_{m=1}^{M} \alpha_{m} h_{m}(\overrightarrow{\mathbf{x}})\right)

算法解析

现有训练数据集:

\mathbb{D}=\left\{\left(\overrightarrow{\mathbf{x}}_{1}, \tilde{y}_{1}\right),\left(\overrightarrow{\mathbf{x}}_{2}, \tilde{y}_{2}\right), \cdots,\left(\overrightarrow{\mathbf{x}}_{N}, \tilde{y}_{N}\right)\right\}, \overrightarrow{\mathbf{x}}_{i} \in \mathcal{X} \subset \mathbb{R}^{n}, \tilde{y}_{i} \in \mathcal{Y}=\{-1,+1\}

初始化训练数据的权值分布 W_{1}=\left(w_{1,1}, w_{1,2}, \cdots, w_{1, N}\right), w_{1, i}=\frac{1}{N}

假设有 m 个学习器,对于 m=1,2, \cdots, M,步骤如下:

  • 使用具有权值分布 W_{m} 的训练数据集学习,根据输入的弱学习算法得到基本分类器:h_{m}(\overrightarrow{\mathbf{x}}) : \mathcal{X} \rightarrow\{-1,+1\}
  • 计算 h_{m}(\overrightarrow{\mathbf{x}}) 在训练数据集上的分类误差率:e_{m}=\sum_{i=1}^{N} w_{m, i} I\left(h_{m}\left(\overrightarrow{\mathbf{x}}_{i}\right) \neq \tilde{y}_{i}\right)。它就是所有误分类点的权重之和。其中权重越大的误差分类点,其在误差率中占比越大。
  • 如果 e_{m} \geq \frac{1}{2},算法终止。
  • \alpha_{m}=\frac{1}{2} \log \frac{1-e_{m}}{e_{m}}。该系数表示 h_{m}(\overrightarrow{\mathbf{x}}) 在集成分类器中的重要性。它是 e_{m} 的单调减函数,说明误差越小的基本分类器,其重要性越高。根据系数大于零要求 e_{m}<\frac{1}{2}
  • 更新训练数据集的权值分布:W_{m+1}=\left(w_{m+1,1}, w_{m+1,2}, \cdots, w_{m+1, N}\right)。其中:w_{m+1, i}=\frac{w_{m, i}}{Z_{m}} \exp \left(-\alpha_{m} \tilde{y}_{i} h_{m}\left(\overrightarrow{\mathbf{x}}_{i}\right)\right)Z_{m}=\sum_{i=1}^{N} w_{m, i} \exp \left(-\alpha_{m} \tilde{y}_{i} h_{m}\left(\overrightarrow{\mathbf{x}}_{i}\right)\right),为规范化因子,它使得 W_{m+1} 成为一个概率分布。

构建基本分类器的线性组合: f(\overrightarrow{\mathbf{x}})=\sum_{m=1}^{M} \alpha_{m} h_{m}(\overrightarrow{\mathbf{x}})。得到集成分类器:H(\overrightarrow{\mathbf{x}})=\operatorname{sign}\left(\sum_{m=1}^{M} \alpha_{m} h_{m}(\overrightarrow{\mathbf{x}})\right)

adaboost-sklearn

sklearn 中 adaboost 使用如下:

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier

ada_clf = AdaBoostClassifier(
    DecisionTreeClassifier(max_depth=4), n_estimators=500)
ada_clf.fit(X_train, y_train)
ada_clf.score(X_test, y_test)
复制代码

集成策略

假定集成包含 M 个基学习器 h_{1}, h_{2}, \cdots, h_{M}。通常有三种集成策略:

  • 平均法。
  • 投票法。
  • 学习法。(stacking 算法,本文暂时跳过)

平均法

平均法通常用于回归任务中。

  • 简单平均法: H(\overrightarrow{\mathbf{x}})=\frac{1}{M} \sum_{i=1}^{M} h_{i}(\overrightarrow{\mathbf{x}})
  • 加权平均法:
\begin{aligned} H(\overrightarrow{\mathbf{x}}) &=\frac{1}{M} \sum_{i=1}^{M} w_{i} h_{i}(\overrightarrow{\mathbf{x}}) \\ w_{i} & \geq 0, \sum_{i=1}^{M} w_{i}=1 \end{aligned}

通常如果个体学习器性能相差较大时,适合使用加权平均法;个体学习器性能相差较近时,适合使用简单平均法。

投票法

投票法通常用于分类任务中。

  • 相对多数投票法:选取得票最多的标记作为预测值: H(\overrightarrow{\mathbf{x}})=\arg \max _{c_{j}} \sum_{i=1}^{M} I\left(h_{i}(\overrightarrow{\mathbf{x}})=c_{j}\right)
  • 加权投票法:类似于加权平均法,其中学习器 h_{i} 的权重 w_{i} 是从训练数据中学的: H(\overrightarrow{\mathbf{x}})=\arg \max _{c_{j}} \sum_{i=1}^{M} w_{i} I\left(h_{i}(\overrightarrow{\mathbf{x}})=c_{j}\right)

TODO

后续补充一下 gbdt 和 stacking 两种集成学习算法。

See Also

sclearn-ensemble

wikipedia-adabootst

wikipedia-gbdt

explain-bias-variance

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/33376
 
209 次点击