【笔记】Bagging和Pasting以及oob(Out-of-Bag)
Bagging和Pasting以及oob(Out-of-Bag)
Bagging和Pasting
前面讲到soft voting classifier和hard voting classifier两个方法,但是这是有很大的问题的,集成学习就是集合多个算法让这几个算法一起计算投票,最后得到好的结果,算法的种类有很多,但是算法的种类再多也是有限的,从投票的角度看,仍然不够,投票票数越多,得到的结果才越好,可以看出来,聚集更多的分类器来得出更好的分类结果是很重要的问题
那么就要创建更多的子模型,集成更多子模型的意见,同时这些子模型之间是不可以一致的,为了保证投票有意义,子模型和子模型之间要具有差异性才可以
那么问题就变成了,怎么创建多个子模型,同时还让每一个子模型都具有差异性,方法就是,每个子模型都只看样本数据的一部分,需要注意的是,尽管这种方法会让每个子模型的准确率降低,但是每个子模型在这种情况下不需要特别高的准确率
假设一个子模型的准确率只有51%,那么如果只有一个子模型,整体的准确度就是51%,但是如果有三个子模型,整体的准确度就是51.5%,计算方式
可以发现是有提升的,如果有五百个子模型,那么整体准确率就是65.6%
可以发现子模型越多,提升越大,这是取51%的准确率,一般不会这么极端,集成学习的威力还是很厉害的
只看样本数据的一部分可以使用两种方式,一种是放回取样,一种是不放回取样,方式操作和名字一样,一般称放回取样的方式为bagging,不放回取样的方式成为pasting,其中bagging更加的常用,因为训练子模型的数量比起pasting要多,同时,bagging不会很依赖随机性,像pasting就很依赖,比如五百个样本,每个子模型取一百个样本,一共就五个模型,模型少不说,划分数据的方式也对最后的结果影响很大,虽然bagging也需要看划分数据的方式,但是因为模型足够多,所以这个随机性就被慢慢抵消掉了
具体实现操作
(在notebook中)
加载好需要的包,还是用虚拟数据,种子为42,绘制图像
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
X,y = datasets.make_moons(n_samples=500,noise=0.3,random_state=42)
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
图像如下
对数据集进行划分
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=42)
因为要集成很多单独的算法,所以这里使用的每一个子模型的算法模型都是决策树模型(决策树更容易产生出差异比较大的子模型)
然后使用sklearn中的BaggingClassifier类,实例化操作一样,传入的参数,首先传入使用的算法,设置子模型数量为500,每一个子模型观察的样本数据为100,将bootstrap参数设置为True,使用放回取样的方式
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500,max_samples=100,
bootstrap=True)
在对数据进行训练以后,计算分类准确度
bagging_clf.fit(X_train,y_train)
bagging_clf.score(X_test,y_test)
结果如下
将子模型的数量设置为5000,然后进行训练,得到训练结果以后计算分类准确度
bagging_clf2 = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=5000,max_samples=100,
bootstrap=True)
bagging_clf2.fit(X_train,y_train)
bagging_clf2.score(X_test,y_test)
结果如下
可以发现,准确度上升了一些,理论上,子模型数量越多,准确度越高
oob(Out-of-Bag)
可以发现,使用放回取样的时候,会导致有些样本可能根本就取不到,平均有37%的样本是取不到的,这部分样本称为oob(out of bag)
在遇到这种情况的时候,其实可以不使用测试数据集,直接使用放回取样中没有取到的样本部分来作为测试数据集就可以
具体实现
(在notebook中)
使用上面的环境布置以及虚拟数据可以得到图像
这里不做数据集的分割,和上面的代码操作大致相同,不过要在BaggingClassifier实例化的时候传入新的参数oob_score,将其设置为True,在计算准确度的时候就可以直接使用oob_score_来得到使用未使用部分的数据的测试准确度
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500,max_samples=100,
bootstrap=True,oob_score=True)
bagging_clf.fit(X,y)
bagging_clf.oob_score_
结果如下
通过bagging可以发现可以发现bagging是很容易并行化处理的,可以使用n_jobs来调节使用的核心数量(并行线路数),为了体现出变化,测试一下时间
%%time
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500,max_samples=100,
bootstrap=True,oob_score=True)
bagging_clf.fit(X,y)
%%time
bagging_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500,max_samples=100,
bootstrap=True,oob_score=True,n_jobs=-1)
bagging_clf.fit(X,y)
结果如下(对比时间可以发现,使用全部核心来处理比默认要快不少)
对于bagging的更多的东西
之前产生差异化的操作是让每一个子模型去看一个更小的数据集,其实还可以使用random_subspaces针对特征进行随机取样,同时还有random_patches(对行和列都进行随机操作),其可以既针对样本,又针对特征进行随机采样
和上面的代码区别不大,添加的参数max_features,代表了每次观察的特征数,这里设置为1,参数bootstrap_features,就是特征的随机采样的方式,设置为True,就是放回取样,关掉样本的随机采样只需要将子模型的最大样本数设置成总体的样本数就可以,设置两个,一个对特征数进行放回取样,一个对样本数量和特征数量都进行放回取样,最后分别训练数据,计算准确度
random_subspaces_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500,
max_samples=500,
bootstrap=True,
oob_score=True,
n_jobs=-1,
max_features=1,
bootstrap_features=True
)
random_subspaces_clf.fit(X,y)
random_subspaces_clf.oob_score_
random_patches_clf = BaggingClassifier(DecisionTreeClassifier(),
n_estimators=500,
max_samples=100,
bootstrap=True,
oob_score=True,
n_jobs=-1,
max_features=1,
bootstrap_features=True
)
random_patches_clf.fit(X,y)
random_patches_clf.oob_score_
结果如下
可以发现,对特征数进行放回取样比对样本数量和特征数量都进行放回取样的准确度要低一些