集成学习 Ensemble Learning
1. 集成学习基本内容
集成学习(ensemble learning)通过构建并结合多个学习器来完成任务,也可以称为“多分类器系统”(multi-classifier system)、“基于委员会学习”(committee-based learning)等。
集成学习结构:先产生一组“个体学习器”(individual learner),再用某种策略将它们结合起来。
同质(homogeneous)- 包含同种类型 集成的个体学习器也可以称为“基学习器”(base learner)。如“决策树集成”、“神经网络集成”。
异质(heterogeneous)- 包含不同类型 集成的个体学习器常被称为“组件学习器”(component learner)。如“同时包含决策树和神经网络的集成”。
集成学习示意图如下:
集成学习中个体学习器的特点:
- 准确性(accuracy)
- 多样性(diversity)
集成学习就是组合这里的多个弱监督模型以期得到一个更好更全面的强监督模型,集成学习潜在的思想是即便某一个弱分类器得到了错误的预测,其他的弱分类器也可以将错误纠正回来。
根据个体学习器的生成方式,将集成学习分为两类:
一是个体学习器间存在强依赖关系、必须串行生成的序列化方法,如 Boosting。
二是个体学习器间不存在强依赖关系、可同时生成的并行化方法,如Bagging和“随机森林”(Random Forest)。
2. Boosting算法
Boosting是一族可将弱学习器提升为强学习器的算法。
该算法工作机制:
(1)从初始训练集训练出一个基学习器;
(2)根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续得到更多关注;
(3)基于调整后的样本分布来训练下一个基学习器;
(4)重复上述步骤,直到基学习器数目达到事先指定的值
T
T
T;
(5)最后,将这
T
T
T个基学习器进行加权结合。
Boosting族算法最著名的代表算法是AdaBoost算法。
AdaBoost算法
AdaBoost(Adaptive boosting)是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。Adaboost算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次得到的分类器最后融合起来,作为最后的决策分类器。
AdaBoost算法:刚开始训练时对每一个训练例赋相等的权重,然后用该算法对训练集训练t轮,每次训练后,对训练失败的训练例赋以较大的权重,也就是让学习算法在每次学习以后更注意学错的样本,从而得到多个预测函数。
基于“加性模型”(additive model),即基学习器的线性组合
H
(
x
)
=
∑
t
=
1
T
α
t
h
t
(
x
)
H(x)=\sum_{t=1}^T\alpha_t h_t(x)
H(x)=t=1∑Tαtht(x)
最小化指数损失函数(exponential loss function)
l
e
x
p
(
H
∣
D
)
=
E
x
∽
D
[
e
−
f
(
x
)
H
(
x
)
]
{\mathscr{l}_{exp}}(H | \mathcal{D})=\mathbb{E}_{x \backsim \mathcal{D}}[e^{-f(x)H(x)}]
lexp(H∣D)=Ex∽D[e−f(x)H(x)]
若
H
(
x
)
H(x)
H(x)能令指数损失函数最小化,则对
H
(
x
)
H(x)
H(x)的偏导
∂
l
e
x
p
(
H
∣
D
)
∂
H
(
x
)
=
−
e
H
(
x
)
P
(
f
(
x
)
=
1
∣
x
)
+
e
H
(
x
)
P
(
f
(
x
)
=
−
1
∣
x
)
\frac {\partial \mathscr{l}_{exp}(H | \mathcal{D})}{\partial H(x)}=-e^{H(x)}P(f(x)=1|x)+e^{H(x)}P(f(x)=-1|x)
∂H(x)∂lexp(H∣D)=−eH(x)P(f(x)=1∣x)+eH(x)P(f(x)=−1∣x)
令其=0,则
H
(
x
)
=
1
2
l
n
P
(
f
(
x
)
=
1
∣
x
)
P
(
f
(
x
)
=
−
1
∣
x
)
H(x)=\frac{1}{2} ln \frac{P(f(x)=1|x)}{P(f(x)=-1|x)}
H(x)=21lnP(f(x)=−1∣x)P(f(x)=1∣x)
s
i
g
n
(
H
(
x
)
)
=
s
i
g
n
(
1
2
l
n
P
(
f
(
x
)
=
1
∣
x
)
P
(
f
(
x
)
=
−
1
∣
x
)
)
sign(H(x))=sign(\frac{1}{2} ln \frac{P(f(x)=1|x)}{P(f(x)=-1|x)})
sign(H(x))=sign(21lnP(f(x)=−1∣x)P(f(x)=1∣x))
=
{
1
,
P
(
f
(
x
)
=
1
∣
x
)
>
P
(
f
(
x
)
=
−
1
∣
x
)
−
1
,
P
(
f
(
x
)
=
1
∣
x
)
<
P
(
f
(
x
)
=
−
1
∣
x
)
\quad \quad \quad \quad \quad \quad \quad \quad =\begin{cases} 1, \quad P(f(x)=1|x)>P(f(x)=-1|x)\\[2ex] -1, \quad P(f(x)=1|x)<P(f(x)=-1|x) \\ \end{cases}
=⎩⎨⎧1,P(f(x)=1∣x)>P(f(x)=−1∣x)−1,P(f(x)=1∣x)<P(f(x)=−1∣x)
=
a
r
g
m
a
x
y
∈
−
1
,
1
P
(
f
(
x
)
=
y
∣
x
)
=\underset{y \in {-1,1}}{arg \; max} P(f(x)=y|x)
=y∈−1,1argmaxP(f(x)=y∣x)
这意味着
s
i
g
n
(
H
(
x
)
)
sign(H(x))
sign(H(x))达到了贝叶斯最优错误率。
3. Bagging与随机森林
Bagging(bootstrap aggregating的简写)
bootstrap也称为自助法,它是一种有放回的采样方法,目的为了得到统计量的分布以及置信区间。
Bagging是并行式集成学习方法最著名的代表。
对于分类任务,使用简单投票法;对于回归任务,使用简单平均法。
算法描述:
与标准AdaBoost只适用于二分类任务不同,Bagging能不经修改地用于多分类、回归等任务。
随机森林(Random Forest,RF)
随机森林是Bagging的一个扩展变体。RF在以决策树为基学习器构建Bagging集成的基础上,进一步在决策树的训练过程中引入了随机属性选择。
优点:随机森林简单、容易实现、计算开销小。
4. 结合策略
学习器结合优势:
(1)从统计方面,由于学习任务的假设空间往往很大,可能有多个假设在训练集上达到同等性能,此时若使用单学习器可能因误选而导致泛化性能不佳,结合多个学习器则会减少这一风险。
(2)从计算方面,学习算法往往会陷入局部极小,有的局部极小点所对应的泛化性能可能很糟糕,而通过多次运行之后进行结合,可降低陷入糟糕局部极小点的风险。
(3)从表示方面,某些学习任务的真实假设可能不在当前学习算法所考虑的假设空间中,此时若单学习器则肯定无效,而通过结合多个学习器,由于相应的假设空间有所扩大,有可能学得更好地近似。
常见的结合策略:
- 平均法(averaging)
a)简单平均法(simple averaging)
b)加权平均法(weighted averaging) - 投票法(voting)
a)绝对多数投票法(majority voting)
b)相对多数投票法(plurality voting)
c)加权投票法(weighted voting) - 学习法,称为次级学习器或元学习器(meta-learner)
a)Stacking算法
b)多响应线性回归(Multi-response Linear Regression, MLR)
用于次级学习算法效果较好。
c)贝叶斯模型平均(Bayes Model Averaging, BMA)
Stacking优于BMA,因为其鲁棒性比BMA更好,而且BMA对模型近似误差非常敏感。
5. sklearn实践
AdaBoost分类器
sklearn.ensemble.AdaBoostClassifier(base_estimator=None, *, n_estimators=50, learning_rate=1.0, algorithm='SAMME.R', random_state=None)
参数说明:
- base_estimator:基分类器,默认是决策树,在该分类器基础上进行boosting,理论上可以是任意一个分类器,但是如果是其他分类器时需要指明样本权重。
- n_estimators:基分类器提升(循环)次数,默认是50次,这个值过大,模型容易过拟合;值过小,模型容易欠拟合。
- learning_rate:学习率,表示梯度收敛速度,默认为1,如果过大,容易错过最优值,如果过小,则收敛速度会很慢;该值需要和n_estimators进行一个权衡,当分类器迭代次数较少时,学习率可以小一些,当迭代次数较多时,学习率可以适当放大。
- algorithm:boosting算法,也就是模型提升准则,有两种方式SAMME, 和SAMME.R两种,默认是SAMME.R,两者的区别主要是弱学习器权重的度量,前者是对样本集预测错误的概率进行划分的,后者是对样本集的预测错误的比例,即错分率进行划分的,默认是用的SAMME.R。
- random_state:随机种子设置。
GridSearchCV自动调参
sklearn.model_selection.GridSearchCV(estimator, param_grid, *, scoring=None, n_jobs=None, iid='deprecated', refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', error_score=nan, return_train_score=False)
GridSearchCV存在的意义就是自动调参,只要把参数输进去,就能给出最优化结果和参数。
参数说明:
- estimator::选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。
- param_grid:需要最优化的参数的取值,值为字典或者列表
- scoring:模型评价标准。
- refit :程序将会以交叉验证训练集得到的最佳参数,重新对所有可能的训练集与开发集进行,作为最终用于性能评估的最佳模型参数。
- n_jobs:并行数,默认为1。
- cv :交叉验证参数,默认None,使用五折交叉验证。
代码
import pandas as pd
from sklearn.datasets import load_wine # 葡萄酒种类数据集
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier # 决策树分类器
from sklearn.ensemble import AdaBoostClassifier # AdaBoost分类器
from sklearn.model_selection import GridSearchCV # 网格搜索自动调参
import matplotlib.pyplot as plt
wine = load_wine()
print(f"所有特征:{wine.feature_names}")
X = pd.DataFrame(wine.data, columns=wine.feature_names)
y = pd.Series(wine.target)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=1)
# 决策树分类器
# max_depth决策树最大深度
# criterion = gini/entropy 可以用来选择用基尼指数或者熵来做损失函数。
base_model = DecisionTreeClassifier(max_depth=1, criterion='gini',random_state=1).fit(X_train, y_train)
y_pred = base_model.predict(X_test) # 预测模型结果
print(f"决策树的准确率:{accuracy_score(y_test,y_pred):.3f}")
from sklearn.ensemble import AdaBoostClassifier
model = AdaBoostClassifier(base_estimator=base_model,
n_estimators=50,
learning_rate=0.5,
algorithm='SAMME.R',
random_state=1)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"AdaBoost的准确率:{accuracy_score(y_test,y_pred):.3f}")
# 测试估计器个数的影响
x = list(range(2, 102, 2))
y = []
for i in x:
model = AdaBoostClassifier(base_estimator=base_model,
n_estimators=i,
learning_rate=0.5,
algorithm='SAMME.R',
random_state=1)
model.fit(X_train, y_train)
model_test_sc = accuracy_score(y_test, model.predict(X_test))
y.append(model_test_sc)
plt.style.use('ggplot')
plt.title("Effect of n_estimators", pad=20)
plt.xlabel("Number of base estimators")
plt.ylabel("Test accuracy of AdaBoost")
plt.plot(x, y)
plt.show()
# 使用GridSearchCV自动调参
# GridSearch和CV,即网格搜索和交叉验证。
# 网格搜索,搜索的是参数,即在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在验证集上精度最高的参数,这其实是一个训练和比较的过程。
hyperparameter_space = {'n_estimators':list(range(2, 102, 2)),
'learning_rate':[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]}
gs = GridSearchCV(AdaBoostClassifier(base_estimator=base_model,
algorithm='SAMME.R',
random_state=1),
param_grid=hyperparameter_space,
scoring="accuracy", n_jobs=-1, cv=5)
gs.fit(X_train, y_train)
print("最优超参数:", gs.best_params_)
参考文献
数据挖掘算法学习(八)Adaboost算法
AdaBoost算法
sklearn.ensemble.AdaBoostClassifier
sklearn中的GridSearchCV方法详解
集成学习(ensemble learning)原理详解
机器学习 - 周志华