取长补短、互通有无 ——集成学习介绍之Bagging &随机森林

2020-06-25  本文已影响0人  StataPython数据分析

取长补短、互通有无 ——集成学习介绍之Bagging &随机森林

本文作者:王 歌
文字编辑:孙晓玲
技术总编:张 邯

我们前面所介绍的都属于个体学习器,也就是由训练数据出发得到的单个学习器,这样做往往泛化性能有限,因此在此基础上,进一步发展了集成学习,也就是将多个个体学习器用某种方法结合在一起,集成之后得到的学习器的泛化能力与单个学习器相比能得到极大提升。
当然,个体学习器的选择也是有一定要求的,一是每个个体学习器都要有一定的准确度,其泛化性能不能太弱;二是个体学习器之间要有一定的差异,这样才能取长补短提升泛化性能。若所集成的个体学习器是同类型的,比如均为SVM算法的学习器,那么这样的集成称为“同质”的,这样的个体学习器称为“基学习器”;反之如果是不同类型的,这样的集成称为“异质”的,其个体学习器称为“组件学习器”或直接称个体学习器。
目前来说同质学习器的应用是更广泛的,我们一般所指的也基本上是同质学习器的集成。而按照个体学习器是否存在依赖关系可以分为Bagging算法Boosting算法两类,前者个体学习器间不存在强依赖关系,可以并行生成个体学习器,后者个体学习器之间存在强依赖关系,需要串行生成个体学习器。我们今天先介绍Bagging算法以及由它扩展出来的随机森林(Random Forest)

1算法介绍

Bagging是基于bootstrap方法的集成学习算法,由于我们要让训练出来的基学习器有一定的差异性,因此我们就要尽可能使训练学习器的训练集之间存在差异。通过使用bootstrap的采样方法,每次都进行有放回的随机采样,然后对每一个样本训练一个个体学习器,然后再将这些学习器结合在一起,这就是Bagging得到学习器的基本流程。
在使用bootstrap生成训练集的过程中,假设每个训练集都含有n个样本,那么在每次抽样中没有被抽中的概率为1-1/n, n次抽样都没有被采集中的概率是(1-1/n)n,当n→∞时,(1-1/n)n→1/e≈0.368,因此约有36.8%的数据没有被抽中,称之为袋外数据(Out Of Bag),它们没有出现在训练集中,可以用来检测模型的泛化能力。

对于分类问题,Bagging在进行结合时使用的是简单投票法,票数最多的类别为最终输出,如果有多个类别票数一样多,通常随机选择一个;对于回归问题则采用简单算术平均的方式,将这些弱学习器得到的回归结果进行算术平均即为最终的输出。

随机森林则是在Bagging基础上的一个扩展。顾名思义,它的每个基学习器都是一棵CART决策树,决策树之间没有关联。假设总属性个数为n,我们之前讲的决策树在选择划分属性时是在当前结点的属性集中选择一个最优属性,而在随机森林中,对每个决策树的结点,先从该结点的属性集中随机选择一个包含k(k<n)个属性的子集,然后再从这个子集中选择一个最优属性用于划分,其他内容则与Bagging算法是一致的。相比于Bagging算法,随机森林增强了基学习器之间的差异性,使得最终集成的学习模型的泛化能力增强。

2类参数介绍

2.1 BaggingClassifier

首先我们说一下Bagging使用的类。在sklearn中,BaggingClassifierBaggingRegressor分别是用于分类和回归的Bagging算法。我们这里主要介绍BaggingClassifier,其主要参数如下:
(1)base_estimator:选择基学习器,默认为决策树;
(2)n_estimators:确定基学习器的个数,默认为10;
(3)max_samples:抽样时的样本量,默认为1.0,接受整型或浮点型;
(4)max_features:训练学习器所需属性的个数,默认为1.0;
(5)bootstrap:是否使用bootstrap,默认为True;
(6)oob_score:是否由袋外样本估计泛化误差,默认为False;
(7)warm_start:是否使用上次训练结果作为初始化参数,默认为False;
(8)n_jobs:表示用CPU的几个内核运行程序,默认为1,当为-1的时候表示用所有CPU的内核运行程序;
(9)random_state:设定随机数种子,默认为None。

2.2 RandomForestClassifier

与Bagging的类相同,随机森林也分为用于分类的RandomForestClassifier和用于回归的RandomForestRegressor类,我们这里主要介绍RandomForestClassifier的参数,该类中有部分参数的用法与BaggingClassifier是一致的,包括n_estimatorsmax_featuresbootstrapoob_scoren_jobsrandom_statewarm_start,还有一部分参数与我们前面介绍的决策树是相同的(复习链接:https://mp.weixin.qq.com/s/vLq0yEgUgG5RZQebjQXEcA),包括criterionmax_depthmin_samples_splitmin_samples_leafmin_weight_fraction_leafmax_leaf_nodesclass_weight。还有两个没有介绍过的参数,一是verbose,用来控制决策树的冗余度,默认为0;二是min_impurity_split,设定分裂的最小不纯度,默认为1e-07。

3算法实例

我们使用的数据依然是我们数据的鸢尾花数据,为了与随机森林的结果形成对比,这里我们在Bagging算法中设定使用k近邻算法作为基学习算法,两个分类器的基学习器数目一致,同时为便于与之前讲决策树时的结果进行对比,因此树的深度等参数都与前面一致,程序如下:

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import RandomForestClassifier

iris_sample = load_iris()
x_train, x_test, y_train, y_test = train_test_split(
    iris_sample.data, iris_sample.target, test_size=0.25, random_state=123)
knclf = KNeighborsClassifier(n_neighbors=5)  # k值设为5
bagclf = BaggingClassifier(
    base_estimator=knclf, n_estimators=10, max_samples=0.5)
rfclf = RandomForestClassifier(n_estimators=10)
bagclf.fit(x_train, y_train)
rfclf.fit(x_train, y_train)
y_bag_pre = bagclf.predict(x_test)
y_rf_pre = rfclf.predict(x_test)
print('真实值:', y_test)
print('bagging预测值:', y_bag_pre)
print('随机森林预测值:', y_rf_pre)
print('bagging预测准确度:', bagclf.score(x_test, y_test))
print('随机森林预测准确度:', rfclf.score(x_test, y_test))

预测结果如下:

image

这里我们可以看到针对这个数据以及参数设置,Bagging算法的准确度稍高一些,与之前决策树中92.11%的准确度相比,无论是Bagging还是随机森林都是要优于单一的决策树的,当然我们还可以通过调参来优化这一结果。同时对于随机森林,我们还可以利用estimators_属性来查看生成的所有树,这里由于我们设置生成了100棵树,篇幅所限就不再展示了。
总体而言,Bagging算法由于使用了bootstrap,因此泛化能力很强,可以降低模型的方差,而随机森林由于可以随机选择结点划分属性,因此在高维时仍可以有效训练,但在噪音较大的数据集上就容易产生过拟合。

以上就是我们今天全部的内容。

上一篇下一篇

猜你喜欢

热点阅读