Bagging
1 Bagging原理
1.1 自助采样法(bootstrap sampling)
给定包含
m
m
m个样本的数据集
D
D
D,我们对其进行采样产生数据集
D
′
D'
D′:每次随机从数据集
D
D
D中挑选一个样本,将其拷贝放进
D
′
D'
D′中,然后再将该样本放回初始数据集
D
D
D中,使得该样本下次仍然可以被采样到;这一过程重复
n
n
n次,就能得到一个包含
n
n
n个样本的的数据集
D
′
D'
D′;初始数据集中有的样本多次被采样,有的则从未被采样。我们做一个简单的估计,在
n
n
n次采样中,样本每次不被采样的概率为
(
1
−
1
m
)
(1-\frac{1}{m})
(1−m1),那么始终不被采样的概率为
(
1
−
1
m
)
n
(1-\frac{1}{m})^n
(1−m1)n,对其取极限:
lim
m
→
∞
(
1
−
1
m
)
n
=
1
e
≈
0.368
\lim_{m \to \infty}(1-\frac{1}{m})^n = \frac{1}{e}\approx 0.368
m→∞lim(1−m1)n=e1≈0.368
由此可见初始数据集中有36.8%的样本未出现在采样数据集
D
′
D'
D′中,采样数据集包含初始数据集63.2%的样本。
1.2 Bagging原理分析
我们欲得到泛化性能强的集成,就需要集成中的个体学习器尽可能相互独立,然而独立在现实中无法做到,因此我们就倾向于使基学习器尽可能具有较大差异。一种做法就是对于给定的数据集,对训练样本进行采样,这样由于训练数据不同,训练得到的基学习器可望具有较大的差异。但是每个采样子集又不能完全不同,这样每个基学习器只利用了一小部分的样本,甚至不足以有效学习,那么就无法确保产出较好的基学习器。
因此我们可以采用自助采样法获得具有相互交叠的子集。我们经过 T T T次自助采样,获得 T T T个含有 n n n个训练样本的采样集,然后基于每个采样集训练一个基学习器,然后再将这些基学习器进行结合,这就是Bagging的基本流程。
在对输出结果进行结合时,对于回归任务通常采用简单平均法,对于分类任务通常采用简单投票法(即每个基学习器使用相同的权重进行平均和投票)。这一结合方式就与投票法相同,那么二者有什么异同呢?我们可以简单的理解为使用投票法之前对数据集进行自助采样就是Bagging方法,二者都是降低方差的技术,因此它在不剪枝决策树、神经网络等易受样本扰动的学习器上效果更加明显。与投票法不同的是,Bagging不仅仅集成模型最后的预测结果,同时采用一定策略来影响基模型训练,保证基模型可以服从一定的假设。在实际的使用中,加入列采样的Bagging技术对高维小样本往往有神奇的效果。
1.3 随机森林(random Forest, RF)
Bagging的一个典型应用是随机森林。在具体实现上,用于每个决策树训练的样本和构建决策树的特征都是通过随机采样得到的,随机森林的预测结果是多个决策树输出的组合(投票)。随机森林的示意图如下:
随机森林相较于决策树的训练过程中引入了随机属性选择。传统决策树在划分属性时是在当前结点的属性集合中选择一个最优的属性;而在随机森林中,对决策树的每个结点,先从该结点的属性集合中随机选择一个包含
k
k
k个属性的子集,然后再从中选择一个最优的属性用于划分。这里
k
k
k控制随机性的引入程度,
k
=
d
k=d
k=d则与传统决策树相同,如果
k
=
1
k=1
k=1则随机选一个属性用于划分,一般情况下推荐
k
=
log
2
d
k=\log_2d
k=log2d。
随机森林优点:
- 简单、以实现、计算开销小;
- 随机森林中基学习器的多样性不仅来自样本扰动,还来自属性扰动,使得泛化性能进一步提升;
- 随机森林的效率常优于Bagging。
2 代码实践
2.1 随机森林回归
使用波士顿房价数据集进行回归分析:
# load dataset
from sklearn import datasets
boston = datasets.load_boston()
X, y = boston.data, boston.target
from sklearn.ensemble import RandomForestRegressor # 随机森林回归
# RandomForestRegressor
ran_reg = RandomForestRegressor()
ran_reg.fit(X,y)
ran_pred = ran_reg.predict(X)
print("模型得分:",explained_variance_score(y,ran_pred))
print("均方误差:",mean_squared_error(y,ran_pred))
模型得分: 0.9833385398396536
均方误差: 1.407009223320158
2.2 随机森林分类
首先创建我们地模拟数据,有100个样本和20维的特征:
# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15,
n_redundant=5, random_state=5)
print(X.shape, y.shape)
x[0]
(1000, 20) (1000,)
array([-4.7705504 , -1.88685058, -0.96057964, 2.53850317, -6.5843005 ,
3.45711663, -7.46225013, 2.01338213, -0.45086384, -1.89314931,
-2.90675203, -0.21214568, -0.9623956 , 3.93862591, 0.06276375,
0.33964269, 4.0835676 , 1.31423977, -2.17983117, 3.1047287 ])
然后利用sklearn包进行训练和预测。
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import BaggingClassifier
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')
# report performance
print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))
Accuracy: 0.860 (0.046)
参考DataWhale开源内容