1.集成学习
集成学习是一种机器学习范式。在集成学习中,我们会训练多个模型(通常称为**「弱学习器」**)解决相同的问题,并将它们结合起来以获得更好的结果。最重要的假设是:当弱模型被正确组合时,我们可以得到更精确和/或更鲁棒的模型。
在集成学习理论中,我们将弱学习器(或基础模型)称为「模型」,这些模型可用作设计更复杂模型的构件。在大多数情况下,这些基本模型本身的性能并不是非常好,这要么是因为它们具有较高的偏置(例如,低自由度模型),要么是因为他们的方差太大导致鲁棒性不强(例如,高自由度模型)。
集成方法的思想是通过将这些弱学习器的偏置和/或方差结合起来,从而创建一个「强学习器」(或「集成模型」),从而获得更好的性能。
组合弱学习器
为了建立一个集成学习方法,我们首先要选择待聚合的基础模型。在大多数情况下(包括在众所周知的 bagging 和 boosting 方法中),我们会使用单一的基础学习算法,这样一来我们就有了以不同方式训练的同质弱学习器。这样得到的集成模型被称为**「同质的」。然而,也有一些方法使用不同种类的基础学习算法**:将一些异质的弱学习器组合成「异质集成模型」。
很重要的一点是:我们对弱学习器的选择应该和我们聚合这些模型的方式相一致。如果我们选择具有低偏差高方差的基础模型,我们应该使用一种倾向于减小方差的聚合方法;而如果我们选择具有低方差高偏差的基础模型,我们应该使用一种倾向于减小偏置的聚合方法。
这就引出了如何组合这些模型的问题。我们可以用三种主要的旨在组合弱学习器的「元算法」:
- bagging,该方法通常考虑的是同质弱学习器,相互独立地并行学习这些弱学习器,并按照某种确定性的平均过程将它们组合起来。
- boosting,该方法通常考虑的也是同质弱学习器。它以一种高度自适应的方法顺序地学习这些弱学习器(每个基础模型都依赖于前面的模型),并按照某种确定性的策略将它们组合起来。
- stacking,该方法通常考虑的是异质弱学习器,并行地学习它们,并通过训练一个「元模型」将它们组合起来,根据不同弱模型的预测结果输出一个最终的预测结果。
非常粗略地说,我们可以说 bagging 的重点在于获得一个方差比其组成部分更小的集成模型,而 boosting 和 stacking 则将主要生成偏置比其组成部分更低的强模型(即使方差也可以被减小)。
2. Bagging(Bootstrap Aggregating )
bagging 是 Bootstrap AGGregatING 的缩写。简而言之,就是通过 bootstrap 取样(可重复取样)的方法构造多个不同的训练集。之后在每个训练集上训练相应的基学习器,最后将这些基学习器聚合起来得到最终的模型。从定义来看,bagging 中有两个重要的部分:
- bootstrap 取样
- 模型聚合(aggregation)
Bagging的算法原理用一张图概括如下:
2. 1 Booststrap采样
自助采样法(bootstrap sampling):
给定包含
m
m
m个样本的数据集
D
D
D,我们对它进行采样产生数据集
D
′
D'
D′: 每次随机从
D
D
D 中挑选一个样本, 将其拷贝放入
D
′
D'
D′ 然后再将该样本放回初始数据集
D
D
D 中,使得该样本在下次采样时仍有可能被采到;这个过程重复执行
m
m
m 次后我们就得到了包含
m
m
m个样本的数据集
D
′
D'
D′,这就是自助采样的结果.显然,
D
D
D 中有一部分样本会在D’中多次出现,而另一部分样本不出现.可以做一个简单的估计,样本在
m
m
m次采样中始终不被采到的概率是
(
1
−
1
m
)
m
(1-\frac{1}{m})^m
(1−m1)m , 取极限得到
lim
x
→
∞
(
1
−
1
m
)
m
=
1
e
≈
0.368
\lim\limits_{x\rightarrow\infty}(1-\frac{1}{m})^m=\frac{1}{e} \approx0.368
x→∞lim(1−m1)m=e1≈0.368
包外估计 (out-of-bagestimate)
通过自助来样,初始数据集 D D D中约有36.8% 的样本未出现在采样数据集 D ′ D' D′中.于是我们可将$D’ $用作训练集, D − D ′ D-D' D−D′用作测试集;这样实际评估的模型与期望评估的模型都使用 m m m个训练、样本,而我们仍有数据总量约1/3 的没在训练集中出现的样本用于测试。这样的测试结果,亦称"包外估计" (out-of-bagestimate).
2.2 模型聚合(aggregation)
通过自助采样法,我们可采样出 T T T个含$m $个训练样本的采样集,然后基于每个采样集单独训练出一个基学习器,再将这些基学习器进行结合。
在对预测输出进行结合时, Bagging对于不同的任务采取不同的方法
- 对于分类任务使用简单投票法,即每个分类器一票进行投票(也可以进行概率平均)
- 对于回归任务,则采用简单平均获取最终结果,即取所有分类器的平均值
若分类预测时出现两个类收到同样票数的情形,则最简单的做法是随机选择一个,也可进一步考察学习器投票的置信度来确定最终胜者。
2.3 算法特点
-
可并行的集成方法。每个基模型可以分别、独立、互不影响地生成。
-
降低 Variance,对 Bias 无明显作用。因此,适用于 High Variance & Low Bias 的模型。
2.4 Bagging算法典型代表–随机森林
随机森林(Random Forest,简称RF是Bagging的一个扩展变体。其在以CART决策树作为基学习器构建Bagging集成的基础上,进一步在决策树的训练过程中引入了随机属性选择。具体来说,传统决策树在选择划分属性时是在当前结点的属性集合(假定有 d d d 个属性)中选择一个最优属性;而在RF中,对基决策树的每个结点,先从该结点的属性集合中随机选择一个包含 k k k 个属性的子集,然后再从这个子集中选择一个最优属性用于划分。这里的参数 k k k 控制了随机性的引入程度:若令 k = d k=d k=d,则基决策树的构建与传统决策树相同;若令 k = 1 k=1 k=1,则是随机选择一个属性用于划分;一般情况下,推荐值 k = l o g 2 d k=log_2d k=log2d。这样进一步增强了模型的泛化能力。
2.4.1 随机森林构建过程
-
在生成每棵决策树时,随机有放回地从训练集中抽取 N N N个训练样本,作为该树的训练集(每棵树的训练集都是不同的,而且里面包含重复的训练样本)。
-
若特征空间共有 D D D个特征,则在每一轮生成决策树的过程中,从 D D D个特征中随机选择其中的 d d d个特征( d < D d<D d<D)组成一个新的特征集,通过使用新的特征集来生成决策树, d d d的选取要是最优的,通常取 d = l o g 2 d d=log_2d d=log2d。通常减小特征选择的个数d,各决策树的相关性和分类能力也会相应降低,增大d,两者也都会随之增大。所以如何选择最优的d是一个关键的问题,也是随机森林的一个重要参数。
-
重复以上两步s次,即建立s个决策树。
-
这s个决策树形成随机森林,对于分类问题,按多棵树分类器投票决定最终分类结果;对于回归问题,由多棵树预测值的均值决定最终预测结果
2.4.2 随机森林的随机特性
随机森林包括两个随机的层面:样本随机、特征选择随机。
样本随机:
如果训练集大小为 N ,对于每棵树而言,随机且有放回地从训练集中的抽取 N 个训练样本,作为该树的训练集。
放回采样,必然导致一部分数据被选中,另外一部分数据没有选中,选中了就放到bag中,没有选中的就是out of bag(oob)
由于袋外样本的存在,这些没有选中的数据不参与建模,所以可以作为验证数据,评估模型效果。因此,随机森林没有必要再进行交叉验证或者用一个独立的测试集来获得误差的一个无偏估计,可以用 oob error 替代。
oob error 计算步骤:
1)对每个样本,计算它作为oob样本的树对它的分类情况(约1/3的树);
2)然后以简单多数投票作为该样本的分类结果;
3)最后用误分个数占样本总数的比率作为随机森林的oob误分率。
举例:
上图中,每行代表一个样本,每列代表一棵树,* 表示参与了模型训练。
观察到,Data 1 参加了 Tree 2,4,6 的训练,没有参加 Tree 1,3,5,7 的训练;
首先将 Data 1 投入没有参与训练的模型中,即 Tree 1,3,5,7 的树模型中,得到4个分类结果,按照简单多数投票,预测Data 1的分类;
在 Data 2,3,4 ,5重复上述过程,取得全部Data的预测分类;
将全部Data的预测分类和实际分类作比较,错误预测Data数 /Data总数,即全部样本的oob误分率。
随机特征
每棵树训练用的特征不是全部特征,**而是随机从M个总特征中选出的m个特征子集,**每次树进行分裂时,从这m个特征中选择最优的;
选变量个数(m)是决策树的重要参数,对系统的调优非常关键。
如果m=M,M表示全部特征数量,则此时RF的CART决策树和普通的CART决策树没有区别。
m取值越小,则模型约健壮,当然此时对于训练集的拟合程度会变差。也就是说m越小,模型的方差会减小,但是偏倚会增大。
在实际案例中,一般会通过交叉验证调参获取一个合适的m值。
2.4.3 随机森林的优缺点
优点:
- 随机森林在解决分类与回归两种类型的问题有很大的优势;
- 随机森林抗过拟合能力比较强;
- 随机森林能处理很高维度的数据(也就是很多特征的数据),并且不用做特征选择,因为建树时会随机选择一些特征作为待选特征子集 ;
- 训练速度快,容易做成并行化方法(训练时,树与树之间是相互独立的) ;
- 随机森林可以做类似于GBDT那样的特征组合;
- 在对缺失数据进行估计时,由于随机丢失特征,随机森林依然十分有效;
- 当存在分类不平衡的情况时,随机森林能够提供平衡数据集误差的有效方法,比如对于 10:1 的数据,将多数数据分为 10份,做 10个 1:1 的单模型然后 Bagging 起来即可。
缺点:
- 随机森林在解决回归问题时,并没有像它在分类中表现的那么好。因为它并不能给出一个连续的输出。当进行回归时,随机森林不能够做出超越训练集数据范围的预测,这可能导致在某些特定噪声的数据进行建模时出现过度拟合。(PS:随机森林已经被证明在某些噪音较大的分类或者回归问题上会过拟合)。
- 对于许多统计建模者来说,随机森林给人的感觉就像一个黑盒子,你无法控制模型内部的运行。只能在不同的参数和随机种子之间进行尝试。
- 可能有很多相似的决策树,掩盖了真实的结果。
- 对于小数据或者低维数据(特征较少的数据),可能不能产生很好的分类。(处理高维数据,处理特征遗失数据,处理不平衡数据是随机森林的长处)。
2.4.4 sklearn 中函数参数介绍
class sklearn.ensemble.``RandomForestClassifier
(n_estimators=100, ***, criterion=‘gini’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=‘auto’, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None, ccp_alpha=0.0, max_samples=None)
提高预测能力
-
n_estimators :int, default=100 整数,可选择(默认值为100):在利用最大投票数或平均值来预测之前,你想要建立子树的数量。一般来说,子树的数量越多,越能提高性能,预测的准确性就越稳定,但是也会放缓计算过程。
-
max_features: 节点分裂时参与判断的最大特征数,
-
如果是int,就要考虑每一次分割处的max_feature特征
-
如果是float,那么max_features就是一个百分比,那么(max_feature*n_features)特征整数值是在每个分割处考虑的。
-
如果是auto,那么max_features=sqrt(n_features),即n_features的平方根值。
-
如果是log2,那么max_features=log2(n_features)
-
如果是None,那么max_features=n_features
注意:寻找分割点不会停止,直到找到最少一个有效的节点划分区,即使它需要有效检查超过max_features的特征。
-
-
min_samples_split:内部节点再划分所需最小样本数。
-
如果为int,那么考虑min_samples_split作为最小的数字。
-
如果为float,那么min_samples_split是一个百分比,并且把ceil(min_samples_split*n_samples)是每一个分割最小的样本数量。
-
加快建模速度
-
n_jobs::用于拟合和预测的并行运行的处理器数量,如果输出值为1,只能使用一个处理器。输出值为-1则意味着没有限制。
-
random_state: 随机数生成器:使模型的输出可复制。当模型具有一个确定的随机数,并且给定相同的超参数和相同的训练数据时,模型将始终产生相同的结果。
-
oob_score是否计算袋外得分,也称作袋外抽样——它是一种随机森林交叉验证方法。在这个样本中,大约三分之一的数据不是用来训练模型,而是用来评估模型的性能。这些样品被称为袋外样品。这一方法与留一法交叉验证非常相似,但几乎没有额外的计算负担。
2.5 代码实战
引入所需要的包
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import BaggingClassifier
创建1000各样本20维特征的随机分类数据集
X, y = make_classification(n_samples=1000, n_features=20,
n_informative=15,n_redundant=5, random_state=5)
print(X.shape, y.shape)
重复分层K-fold 交叉验证评估模型-模型为bagging
# 一共重复3次,每次10fold,评估模型在所有重复交叉验证中性能的平均值和标准差
# define model
model = BaggingClassifier()
# evaluate the model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
# repeat performance
print("Accuracy: %.3f (%.3f)" % (mean(n_scores), std(n_scores)))
函数注解:
RepeatedStratifiedKFold(n_splits=K, n_repeats=n, random_state):重复分层k折交叉验证器,重复K折n次
- n_splits: 折数 (>=2)
- n_repeats: 交叉验证器重复的次数
- random_state: 随机数种子
sklearn.cross_validation.cross_val_score(estimator, X, y=None, scoring=None,cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’)
作用:交叉验证
- estimator:估计方法对象(分类器)
- X:数据特征(Features)
- y:数据标签(Labels)
- soring:调用方法(包括accuracy和mean_squared_error等等)
- cv:几折交叉验证
- n_jobs:同时工作的cpu个数(-1代表全部)
- error_score:如果在估计器拟合中发生错误,要分配给该分数的值(一般不需要指定)
ator:估计方法对象(分类器)
- X:数据特征(Features)
- y:数据标签(Labels)
- soring:调用方法(包括accuracy和mean_squared_error等等)
- cv:几折交叉验证
- n_jobs:同时工作的cpu个数(-1代表全部)
- error_score:如果在估计器拟合中发生错误,要分配给该分数的值(一般不需要指定)