上一次我们讲到了决策树的应用,但其实我们发现单棵决策树的效果并不是那么的好,有什么办法可以提升决策树的效果呢?这就是今天要提到的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 np
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.ensemble import BaggingClassifier
from sklearn import datasets#读取数据,划分训练集和测试集
iris=datasets.load_iris()
x=iris.data[:,:2]
y=iris.target
x_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_test
res2=model2_pre==y_test
print '决策树测试集正确率%.2f%%'%np.mean(res1*100)
print 'Bagging测试集正确率%.2f%%'%np.mean(res2*100)
结果如下
决策树测试集正确率75.56%
Bagging测试集正确率77.78%
【机器学习|机器学习笔记(六)Bagging及随机森林】似乎结果并不如我们之前想象的那么美好啊,原以为会有的巨大提升并没有显示出来。分析一下原因
1 也许Bagging中所做的这100的分类器并不是完全独立的,所以提升效果没有预想的那么好。
2 这也很有可能是我们所用的这个数据集太小,并且也没有很多局部的细节特征所以导致效果不是很好。这里我说一点自己的理解,感觉Bagging真正厉害的地方在于可以通过抽样实现对样本某些局部细节特征的把握,但如果在整个区间内的特征都是比较一致的,反而显示不出这种方法的优势了。这是我自己的一点想法,并不一定正确,欢迎拍砖。
为了证明Bagging的这种优势,接下来我们做一个回归问题,这样可以比较容易设置局部的细节特征。
首先是造一些数据。我们在[-3,3]用两个高斯函数叠加一些噪声造一批数据,然后分别用决策树和Bagging回归器进行拟合,看看二者的预测效果相差多少。
import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import BaggingRegressor
from matplotlib import pyplot as plt
import matplotlib as mpl
#源函数
def f(x):
return np.exp(-x**2)+0.8*np.exp(-(x-2)**2)
#构造数据
np.random.seed(0)
N=200
x=np.random.rand(N)*6-3
x=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'] = False
plt.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 np
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn import datasets#读取数据,划分训练集和测试集
iris=datasets.load_iris()
x=iris.data[:,:2]
y=iris.target
x_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_train
res2=model2_pre==y_train
print '决策树训练集正确率%.2f%%'%np.mean(res1*100)
print '随机森林训练集正确率%.2f%%'%np.mean(res2*100)
输出结果为
决策树训练集正确率83.81%
随机森林训练集正确率85.71%
和Bagging的效果差不多啊,下次拿个数据量大的试一试,不管怎么样,方法掌握了就行。
好的,祝大家周末剩下的半天愉快,O(∩_∩)O哈哈哈~
推荐阅读
- paddle|动手从头实现LSTM
- 人工智能|干货!人体姿态估计与运动预测
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- 分析COMP122 The Caesar Cipher
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- 读书笔记|《白话大数据和机器学习》学习笔记1
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例