机器学习笔记(六)Bagging及随机森林

来源:互联网 发布:咸阳办公软件电脑培训 编辑:程序博客网 时间:2024/04/28 02:43

上一次我们讲到了决策树的应用,但其实我们发现单棵决策树的效果并不是那么的好,有什么办法可以提升决策树的效果呢?这就是今天要提到的Bagging思想。

其实对于Bagging早有耳闻,知道它是一种提升的办法,但之前总在想它的名字是什么含义?装袋?是通过某种抽样的意思吗?对了一半,它确实和抽样有关,但并不是什么装袋,Bagging是Bootstrap aggregation的缩写,直译就是有放回抽样的集合,事实上它也是这么做的,基本的过程如下所示:

1 从样本有重复地抽取n个样本

2 在所有的属性上,对这n个样本建立分类器

3 重复上述过程m次,得到m个分类器

4 将数据放在这m个分类器上分类,最终结果由所有分类器结果投票决定

其实也就是说,我拿到训练集后,我不是一下子把所有的数据都拿去训练,得到一个分类器做一锤子买卖。而是不断地从中选出若干个数据,然后用这若干个数据训练得到若干个分类器,再把测试数据放在这若干个分类器上用投票得到最终的结果。那如果我每个分类器分类正确的概率是60%,假如这若干个分类器是独立的,那么我用10个分类器,那么最终得到正确答案的概率就是1-40%^10=99.99%,是不是质的提升呢O(∩_∩)O~所以啊,弱分类器没关系,我有Bagging啊,人多力量大,三个臭皮匠还顶一个诸葛亮呢。

接下来,我们来实际见证一下Bagging对分类器的提升。

同样的还是上回所用的鸢尾花数据,我们用决策树分类器和Bagging分类器分别做一次比较一下差距在哪儿

import numpy as npfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.ensemble import BaggingClassifierfrom sklearn import datasets#读取数据,划分训练集和测试集iris=datasets.load_iris()x=iris.data[:,:2]y=iris.targetx_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.7, random_state=1)#模型训练model1=DecisionTreeClassifier(max_depth=5)model2=BaggingClassifier(model1,n_estimators=100,max_samples=0.3)model1.fit(x_train,y_train)model2.fit(x_train,y_train)model1_pre=model1.predict(x_test)model2_pre=model2.predict(x_test)res1=model1_pre==y_testres2=model2_pre==y_testprint '决策树测试集正确率%.2f%%'%np.mean(res1*100)print 'Bagging测试集正确率%.2f%%'%np.mean(res2*100)

结果如下

决策树测试集正确率75.56%

Bagging测试集正确率77.78%

似乎结果并不如我们之前想象的那么美好啊,原以为会有的巨大提升并没有显示出来。分析一下原因

1 也许Bagging中所做的这100的分类器并不是完全独立的,所以提升效果没有预想的那么好。

2 这也很有可能是我们所用的这个数据集太小,并且也没有很多局部的细节特征所以导致效果不是很好。这里我说一点自己的理解,感觉Bagging真正厉害的地方在于可以通过抽样实现对样本某些局部细节特征的把握,但如果在整个区间内的特征都是比较一致的,反而显示不出这种方法的优势了。这是我自己的一点想法,并不一定正确,欢迎拍砖。

为了证明Bagging的这种优势,接下来我们做一个回归问题,这样可以比较容易设置局部的细节特征。

首先是造一些数据。我们在[-3,3]用两个高斯函数叠加一些噪声造一批数据,然后分别用决策树和Bagging回归器进行拟合,看看二者的预测效果相差多少。

import numpy as npfrom sklearn.tree import DecisionTreeRegressorfrom sklearn.ensemble import BaggingRegressorfrom matplotlib import pyplot as pltimport matplotlib as mpl#源函数def f(x):    return np.exp(-x**2)+0.8*np.exp(-(x-2)**2)#构造数据   np.random.seed(0)N=200x=np.random.rand(N)*6-3x=np.sort(x).reshape(-1,1)y=f(x)+0.05*np.random.randn(N).reshape(-1,1)#构造分类器并拟合model1=DecisionTreeRegressor(max_depth=5)model2=BaggingRegressor(n_estimators=100,max_samples=0.3)model1.fit(x,y)model2.fit(x,y)#预测数据,区间略大于初始区间x_test=(np.linspace(-3,3,100)*1.5).reshape(-1,1)model1_pre=model1.predict(x_test)model2_pre=model2.predict(x_test)#画图mpl.rcParams['font.sans-serif'] = [u'SimHei']mpl.rcParams['axes.unicode_minus'] = Falseplt.plot(x_test,f(x_test),'g-',lw=2,label=u'目标数据')plt.plot(x,y,'r-',lw=2,label=u'训练数据')plt.plot(x_test,model1_pre,'b^',lw=2,label=u'决策树预测')plt.plot(x_test,model2_pre,'k*',lw=2,label=u'Bagging预测')plt.legend(loc='upper left')plt.grid()plt.show()

输出结果如下:


从图上可以看到,虽然两者在正方向后来的预测都不是十分准确,但是Bagging的优势还是很明显的。在样本的两个峰值处,Bagging回归器都顺利回到了峰值,而决策树则是平的过去,Bagging的效果是明显好于决策树,所以在大多数情况下,Bagging的方法还是有效的,可以为我们的模型预测效果带来一定的提高。

那既然Bagging是在样本上做抽样,聪明的你一定想到了,那我们可不可以在特征上也进行抽样呢?非常棒,答案是yes。如果我们用的是CART树,那么这种方法我们称之为随机森林,就是那个大名鼎鼎在很多数据比赛中大放异彩的家伙。

这里还是简单叙述一下随机森林的整个过程:

1 首先在样本集中有放回的抽样n个样本

2 在所有的属性当中再随机选择K个属性

3 根据这n个样本的K个属性,建立CART树

4 重复以上过程m次,得到了m棵CART树

5 利用这m棵树对样本进行预测并投票

其实过程和Bagging几乎无异,只是增加了一个随机特征选择的过程。

写到这儿的时候我突然想到了上面有一个地方好像不太合适!!!

在上面的Bagging测试代码中,我比较的是测试集的准确率,突然有了个不成熟的小建议,比较的应该是训练集的准确率才对吧!!!稍微改一下,看下结果:

决策树训练集正确率84.76%

Bagging训练集正确率86.67%

好像还是没多大的变化啊摔!

最后给一个随机森林和决策树的比较吧,虽然还是鸢尾花的小样本,但是看一下sklearn中的它的使用流程也好

import numpy as npfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.ensemble import RandomForestClassifierfrom sklearn import datasets#读取数据,划分训练集和测试集iris=datasets.load_iris()x=iris.data[:,:2]y=iris.targetx_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.7, random_state=1)#模型训练model1=DecisionTreeClassifier(max_depth=3)model2=RandomForestClassifier(n_estimators=200, criterion='entropy', max_depth=3)model1.fit(x_train,y_train)model2.fit(x_train,y_train)model1_pre=model1.predict(x_train)model2_pre=model2.predict(x_train)res1=model1_pre==y_trainres2=model2_pre==y_trainprint '决策树训练集正确率%.2f%%'%np.mean(res1*100)print '随机森林训练集正确率%.2f%%'%np.mean(res2*100)

输出结果为

决策树训练集正确率83.81%

随机森林训练集正确率85.71%

和Bagging的效果差不多啊,下次拿个数据量大的试一试,不管怎么样,方法掌握了就行。

好的,祝大家周末剩下的半天愉快,O(∩_∩)O哈哈哈~





0 0