集成学习(ensemble learning)基础知识
写在前面:
这是一篇只大体梳理集成学习(ensemble learning)基础知识的博客,如果你已经对集成学习很熟悉了,完全可以跳过了。本博客为周志华《机器学习》第8章集成学习的读书笔记,虽有自己微小的理解补充,但大部分内容依然来自西瓜书。
集成学习系列博客:
- 集成学习(ensemble learning)基础知识
- 随机森林(random forest)
本科时粗浅的搞过一段时间的集成学习,当然正如前面所说,就真的是很粗浅的,今日再次温故从而知新。集成学习以其强大的性能几乎成为各大数据挖掘比赛的必备之物了,集成学习用最简答的话来描述,即:“三个臭皮匠,赛过诸葛亮”。这篇博客主要从以下几个方面介绍集成学习:
- 什么是集成学习
- 集成学习方法的分类
- 多样性增强的几种方法
一、什么是集成学习
集成学习是通过构建并结合多个学习器来完成学习任务,如下图所示,其过程是:先产生一组“个体学习器”,再用某种策略将它们结合起来。个体学习器一般就是我们常见的机器学习算法,比如:决策树,神经网络等。这里集成一般有两种:同质和异质。同质是指个体学习器全是同一类型,这种同质集成中的个体学习器又称“基学习器”。异质是指个体学习器包含不同类型得学习算法,比如同时包含决策树和神经网络。一般我们常用的都是同质的,即个体学习器都是同一类型的。

集成学习通过将多个基学习器结合,通常都会获得比单一学习器显著优越的泛化性能。下面看个例子(例子来自周志华《机器学习》),来看看集成学习是如何获得比最好的单一学习器更好的性能的。假定在一个二分类任务中,三个分类器在三个测试样本上的表现如下图所示,其中, h i h_i hi表示第 i i i个分类器, √ √ √表示分类正确, × × ×表示分类错误,集成的结果通过投票法产生(少数服从多数原则)。

在图(a)中,能够看出,每个基分类器都只有66%的准确率,但是集成后精读达到了100%。而在图(b)中,三个分类器没有差别,集成后性能没有提升,依然是66%。在图(c)中,每个基分类器的准确率只有33%,集成后性能反而变得更糟,0%。从这个简单的例子中,我们能够得出:
要想获得较好的集成性能,基分类器需要满足两个基本条件:
- 基分类器要有一定的性能,至少不差于随机猜测的性能,即基分类器准确率不低于50%。
- 基学习器要具有多样性,即基学习器间要有差异性,不能像上图(b)中那样,三个基分类器都一样。提升集成学习性能主要通过这一条“多样性”来做,因为第一条很容易满足。
以下内容为可选,有兴趣的看下即可,对公式头大的直接略过也没关系,证明参考:南瓜书PumpkinBook,我只是对其中每一步做了解释。
西瓜书上还有一段证明,证明在基学习器误差相互独立的情况下,集成学习的错误率随着基分类器数目的增大,呈指数下降,最终趋向于0。我们这里顺手证明下吧,对公式头大的同学可以跳过了,只需记住结论即可。这也只是在理想情况下,即基学习器误差相互独立的情况下,在实际情况中显然是不可能的。
证明:
证明之前先来看下 hoeffding inequality(懒得打公式了,直接放图片,图片来自:CS229 Supplemental Lecture notes Hoeffding’s inequality)

下面开始证明,考虑二分类问题
y
∈
{
−
1
,
+
1
}
y \in \{-1, +1\}
y∈{−1,+1}和真实函数
f
f
f,假定基分类器的错误率为
ϵ
\epsilon
ϵ,即对每个基分类器
h
i
h_i
hi有:
P
(
h
i
(
x
)
=
̸
f
(
x
)
)
=
ϵ
P(h_i(x) =\not\ f(x)) = \epsilon
P(hi(x)≠ f(x))=ϵ
假设通过简单投票法结合
T
T
T个分类器,若有超过半数的基分类器正确,则集成分类就正确:
H
(
x
)
=
s
i
g
n
(
∑
i
=
1
T
h
i
(
x
)
)
H(x) = sign(\sum_{i=1}^{T}h_i(x))
H(x)=sign(i=1∑Thi(x))
假设基分类器的错误率相互独立,我们有:
P
(
H
(
x
)
=
̸
f
(
x
)
)
=
∑
k
=
0
⌊
T
/
2
⌋
(
T
k
)
(
1
−
ϵ
)
k
ϵ
T
−
k
P(H(x) =\not\ f(x)) = \sum_{k=0}^{\left \lfloor T/2 \right \rfloor}\binom{T}{k}(1-\epsilon )^{k}\epsilon ^{T-k}
P(H(x)≠ f(x))=k=0∑⌊T/2⌋(kT)(1−ϵ)kϵT−k
解释下这个公式,
ϵ
\epsilon
ϵ表示基分类器的错误率,则
1
−
ϵ
1-\epsilon
1−ϵ为正确率。所以,集成学习分类错误的情况就是分错的基分类器数量超过一半,也就是分对的基分类器数量少于一半,所以是
⌊
T
/
2
⌋
\left \lfloor T/2 \right \rfloor
⌊T/2⌋。假设
X
X
X 为
T
T
T 个基分类器分类正确的次数,因为是个二分类问题,又因为做了多次(T个基分类器,每个看做抛一次硬币),则随机变量显然服从二项分布的(n重伯努利试验),所以
X
∼
B
(
T
,
1
−
ϵ
)
X\sim B(T, 1-\epsilon)
X∼B(T,1−ϵ),因此:

这里来解释下上面的公式,
(
1
)
→
(
2
)
(1)\rightarrow (2)
(1)→(2)这一步无需多言了,就做了个缩放,目的是为了把下取整去掉。
(
2
)
→
(
3
)
(2)\rightarrow (3)
(2)→(3)要想用 hoeffding inequality,肯定还是要想往这个公式的形式上凑,从 hoeffding inequality 公式定义看,
P
(
1
n
∑
i
=
0
n
(
Z
i
−
E
[
Z
i
]
)
≤
−
t
)
P(\frac{1}{n}\sum_{i=0}^{n}(Z_i - \mathbb{E}[Z_i]) \leq -t)
P(n1∑i=0n(Zi−E[Zi])≤−t),我们来做个变形(用
Z
Z
Z表示
Z
1
+
Z
2
+
.
.
.
+
Z
n
Z_1 + Z_2 +... + Z_n
Z1+Z2+...+Zn),
P
(
Z
−
E
[
Z
]
)
≤
−
n
t
)
P(Z - \mathbb{E}[Z]) \leq -nt)
P(Z−E[Z])≤−nt),所以这一步才会两边同时减去
(
1
−
ϵ
)
T
(1-\epsilon)T
(1−ϵ)T,这个就是正确次数的数学期望(概率乘总次数),这样当
t
=
(
1
−
2
ϵ
)
2
t=\frac{(1-2\epsilon)}{2}
t=2(1−2ϵ),就变成了 hoeffding inequality 的左边,那么直接用 hoeffding inequality ,则有:
P
[
X
−
(
1
−
ϵ
)
T
≤
−
T
2
(
1
−
2
ϵ
)
]
≤
e
x
p
(
−
1
2
T
(
1
−
2
ϵ
)
2
)
P[X - (1-\epsilon )T \leq -\frac{T}{2}(1-2\epsilon )] \leq exp(-\frac{1}{2}T(1-2\epsilon)^2)
P[X−(1−ϵ)T≤−2T(1−2ϵ)]≤exp(−21T(1−2ϵ)2)
也即:
P
(
H
(
x
)
=
̸
f
(
x
)
)
≤
e
x
p
(
−
1
2
T
(
1
−
2
ϵ
)
2
)
P(H(x) =\not\ f(x)) \leq exp(-\frac{1}{2}T(1-2\epsilon)^2)
P(H(x)≠ f(x))≤exp(−21T(1−2ϵ)2)
因此,从上式能够看出,当基分类器数量
T
→
+
∞
T \rightarrow +\infty
T→+∞,则集成模型的错误率趋向于0。
二、集成学习方法的分类
关于集成学习常见的结合方法,目前大多数的资料(如 周志华《机器学习》,Pang-Ning Tan(陈封能)introduction to data mining等)把其分为两大类,第一类为Boosting,这一类个体之间学习器之间存在强依赖关系,必须使用串行的方法去学习。另外一类为Bagging,这一类方法个体学习器之间不存在强依赖关系,因此可用并行的方式去学习。关于Stacking方法要不要单独分为一类,我个人觉得可以把其分为一类。大家要是用于学术论文等比较严谨的场合还是以西瓜书为准,即分为两大类(boost和bagging),周老师把stacking方法归到了结合策略中。我这里把其分为三类(依据见wiki:Ensemble learning),
即Boosting、Bagging和Stacking。
2.1 Bagging
Bagging的主要思想如下图所示,首先从数据集中采样出T个数据集,然后基于这T个数据集,每个训练出一个基分类器,再讲这些基分类器进行组合做出预测。Bagging在做预测时,对于分类任务,使用简单的投票法。对于回归任务使用简单平均法。若分类预测时出现两个类票数一样时,则随机选择一个。

从上面的图中也能够看出,Bagging非常适合并行处理,这对于大数据量下非常有好处。关于从原始数据集里采样出m个数据集,这里要说下,我们希望能够产生m个不同的子集,因为这样训练出来的基分类器具有比较大的差异,满足开头所说的“多样性”,有助于提高集成算法最终的性能。但是呢,又不能让基分类器性能太差,比如我们采样时,采样出来的子集每个都完全不相同,这样训练出来的基分类器性能就比较差,因为每个基分类器相当于只用了一小部分数据去训练。因此,Bagging中采样自助采样法(bootstrap sampling)。
自助采样法(bootstrap sampling)
这个其实就是有放回的采样,每个采样出来的样本集都和原始数据集一样大。假如给定包含m个样本的数据集,我们先随机取出一个样本放入采样集中,然后再把该样本放回去,使得下次这个样本还有可能被选中,这样经过m次随机采样,我们得到包含m个样本的采样集,原始数据集中有的样本在采样集多次出现,有的则未出现。采样集中大约包含63.2%的原始数据,因为每个样本被抽到的概率为
1
m
\frac{1}{m}
m1,则样本在m次采样中始终没被采到的概率为
(
1
−
1
m
)
m
(1-\frac{1}{m})^m
(1−m1)m,当
m
→
∞
m \rightarrow \infty
m→∞时,其极限为
1
e
≈
0.368
\frac{1}{e}\approx 0.368
e1≈0.368。
从偏差-方差分解的角度看,Bagging主要关注降低方差。
2.2 Boosting
与Bagging能够并行处理不同,Boosting由于各基学习器之间存在强依赖关系,因此只能串行处理,也就是说Boosting实际上是个迭代学习的过程。Boosting的工作机制为:先从初始训练集中训练出一个基学习器,再根据基学习器的表现对训练样本分布进行调整(比如增大被误分样本的权重,减小被正确分类样本的权重),使得先前基学习器做错的样本在后续的训练过程中受到更多关注,然后基于调整后的样本分布来训练下一个基学习器,如此重复,直到基学习器数目达到事先自定的值 T T T,然后将这 T T T个基学习器进行加权结合(比如错误率小的基学习器权重大,错误率大的基学习器权重小,这样做决策时,错误率小的基本学习器影响更大)。Boosting算法的典型代表有AdaBoost和XGBoost。Boosting算法可以用下图简略形象的描述下:

从偏差-方差分解的角度看,Boosting主要关注降低偏差。
2.3 Stacking
Stacking方法是先从初始数据集训练出初级学习器,然后“生成”一个新的数据集用于训练次级学习器。在这个新的数据集中,初级学习器的输出被当做样例输入特征,而初始样本的标记仍然被当做样例标记。其学习过程如下图所示:

其算法伪代码如下所示(截自周志华《机器学习》):

这里有个需要注意的是,如果直接用初级学习器的训练集来产生次级训练集,则过拟合风险比较大。一般的处理办法是使用交叉验证来做,以k折交叉验证为例,初始训练集 D D D被随机划分为 k k k个大小相等的数据集 D = { D 1 , D 2 , . . . , D k } D = \{D_1,D_2,...,D_k\} D={D1,D2,...,Dk},假设 D j D_j Dj表示第 j j j折的测试集,则 D j ‾ = D ∖ D j \overline{D_j}=D \setminus D_j Dj=D∖Dj表示第 j j j折的训练集。给定 T T T个初级学习算法,初级学习器 h t ( j ) h_t^{(j)} ht(j)是第 t t t个学习器在 D j ‾ \overline{D_j} Dj上学习而得。对 D j D_j Dj中每个样本 x i x_i xi,令 z i t = h t ( j ) ( x i ) z_{it} = h_t^{(j)}(x_i) zit=ht(j)(xi),则由 x i x_i xi所产生的次级训练样本特征为 z i = ( z i 1 , z i 2 , . . . , z i T ) z_{i} = (z_{i1},z_{i2},...,z_{iT}) zi=(zi1,zi2,...,ziT),label为 y i y_i yi。因此,在整个交叉验证过程结束后,从这 T T T个初级学习器产生的次级训练集是 D ′ = { ( z i , y i ) } i = 1 m D' = \{(z_i,y_i)\}_{i=1}^m D′={(zi,yi)}i=1m,然后将 D ′ D' D′用于训练次级学习器。

stacking这个基本上在kaggle比赛里是神器。。。
二、多样性增强的几种方法
在博客开头也说过,想要提高集成算法的性能,基学习器多样性是个很重要的。那么到底该如何增强多样性呢?一般的做法主要是对数据样本,输入属性,输出表示,算法参数进行扰动。
-
数据样本扰动
这个其实主要就是采样,比如在bagging中的自助采样法,数据样本扰动对决策树,神经网络这样对数据样本变化非常敏感的学习算法非常有效,但是对支持向量机,朴素贝叶斯,k近邻这些对样本扰动不敏感的算法没用。对此类算法作为基学习器进行集成时往往需要使用输入属性扰动等机制。 -
输入属性扰动
这个就是从样本的特征空间中产生不同的特征子集。这样训练出来的基学习器必然是不同的。在包含大量冗余属性的数据,在特征子集中训练基学习器不仅能产生多样性大的个体,还会因属性数的减少而大幅节省时间开销,同时,由于冗余属性多,减少一些冗余属性后训练出来的基学习器性能也不会差。若数据只包含少量属性,或者冗余属性少,则不适宜使用输入属性扰动法。 -
输出表示扰动
这类做法的基本思路是对输出表示进行操纵以增强多样性。比如可对训练样本的label稍作变动,比如“翻转法”随机改变一些训练样本的标记;也可以对输出表示进行转化,如“输出调制法”将分类输出转化为回归输出后构建基学习器。这一类貌似用的不多。 -
算法参数扰动
这个在现在深度学习比赛中很常见,主要是神经网络有很多参数可以设置,不同的参数往往可以产生差别比较大的基学习器。
关于集成学习(ensemble learning)的基础知识就介绍到,后面博客会相继介绍随机森林,AdaBoost,GBDT等具体的集成学习算法。