Bagging
是Bootstrap Aggregating
的简称,意思就是再取样(Bootstrap
)然后在每个样本上训练出来的模型进行集成.
通常如果目标是分类,则集成的方式是投票;如果目标是回归,则集成方式是取平均.
在集成算法中,bagging
方法会在原始训练集的随机子集上构建一类黑盒估计器的多个实例,然后把这些估计器的预测结果结合起来形成最终的预测结果.
该方法通过在训练模型的过程中引入随机性,来减少基估计器的方差(例如,决策树).在多数情况下,bagging
方法提供了一种非常简单的方式来对单一模型进行改进,而无需修改背后的算法.因为bagging
方法可以减小过拟合(variance),所以通常在强分类器和复杂模型上使用时表现的很好.
bagging
方法有很多种,其主要区别在于随机抽取训练子集的方法不同:
粘贴(Pasting)
.Bagging
.随机子空间(Random Subspaces)
随机补丁(Random Patches)
bagging的另一个好处是天生的易于并行.完全可以多个机器同时训练,之后再集成起来,这样可以大大提高效率.
In [1]:
import requests
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder,StandardScaler
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report
from sklearn.ensemble import BaggingClassifier
In [2]:
csv_content = requests.get("http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data").text
row_name = ['sepal_length','sepal_width','petal_length','petal_width','label']
csv_list = csv_content.strip().split("\n")
row_matrix = [line.strip().split(",") for line in csv_list]
dataset = pd.DataFrame(row_matrix,columns=row_name)
encs = {}
encs["feature"] = StandardScaler()
encs["feature"].fit(dataset[row_name[:-1]])
table = pd.DataFrame(encs["feature"].transform(dataset[row_name[:-1]]),columns=row_name[:-1])
encs["label"]=LabelEncoder()
encs["label"].fit(dataset["label"])
table["label"] = encs["label"].transform(dataset["label"])
In [3]:
table[:10]
Out[3]:
In [4]:
train_set,validation_set = train_test_split(table)
In [5]:
bagging = BaggingClassifier(MLPClassifier(),n_estimators=15,max_samples=0.5, max_features=0.5,n_jobs=4)
In [6]:
bagging.fit(train_set[row_name[:-1]], train_set["label"])
Out[6]:
In [7]:
pre = bagging.predict(validation_set[row_name[:-1]])
In [8]:
print(classification_report(validation_set["label"],pre))
随机森林是最知名的bagging应用,利用多个随机树实例投票进行预测分类或者求平均做回归预测(cart tree
使用基尼系数而非信息熵,因此可以处理连续数据).
sklearn中提供了4个随机森林接口:
接口 | 说明 |
---|---|
ensemble.RandomForestClassifier([…]) |
随机森林分类器 |
ensemble.RandomForestRegressor([…]) |
随机森林回归器 |
ensemble.ExtraTreesClassifier([…]) |
极限随机树分类器 |
ensemble.ExtraTreesRegressor([n_estimators, …]) |
极限随机树回归器 |
在计算分割点方法中的随机性进一步增强.
其中极限随机树是RF的一个变种,原理几乎和RF一模一样,仅有区别有:
在决策树节点的划分决策的时候,RF采用的是随机选择一部分特征来选择划分特征,而extra trees还是比较符合bagging的传统,基于所有的特征来选择划分特征.
在选定了划分特征后,RF的决策树会基于信息增益,基尼系数,均方差之类的原则,选择一个最优的特征值划分点,这和传统的决策树相同.但是extra trees比较的激进,他会随机的选择一个特征值来划分决策树.
随机森林的原理不多复述,这里主要给出利用sklearn中接口的例子:
In [9]:
from sklearn.ensemble import RandomForestClassifier
In [10]:
rfc = RandomForestClassifier(n_estimators=1000,n_jobs=4)
In [11]:
rfc.fit(train_set[row_name[:-1]], train_set["label"])
Out[11]:
In [12]:
pre = rfc.predict(validation_set[row_name[:-1]])
In [13]:
print(classification_report(validation_set["label"],pre))
使用上述这些方法时要调整的参数主要是
n_estimators
是森林里树的数量.
通常数量越大,效果越好,但是计算时间也会随之增加.此外要注意,当树的数量超过一个临界值之后,算法的效果并不会很显著地变好.
max_features
是分割节点时考虑的特征的随机子集的大小.
这个值越低,方差减小得越多(泛化能力变强).但是偏差的增大也越多(准确率变差).根据经验,回归问题中使max_features = n_features
,分类问题使 max_features = sqrt(n_features)
(其中n_features
是特征的个数)是比较好的默认值.
max_depth = None和min_samples_split=2 结合通常会有不错的效果(即生成完全的树)
.
通常默认的参数通常不是最佳的,同时还可能消耗大量的内存,最佳参数值应由交叉验证获得.
另外要请注意:
当使用自助采样法方法抽样时,泛化精度是可以通过剩余的或者袋外的样本来估算的.设置oob_score = True
即可实现.