目录
1 集成学习的三大关键领域
2 Bagging方法的基本思想
3 随机森林RandomForest
3.1 RandomForestRegressor的实现
3.1.1 导入模块
3.1.2 导入数据
3.1.3 交叉验证及建模
4 随机森林在巨量数据上的增量学习
4.1 普通学习vs增量学习
4.1.1 对sklearn自带数据集进行训练
4.1.2 同样模型训练kaggle数据集
4.1.3 对sklearn自带数据集进行训练
4.1.4 同样模型训练kaggle数据集
集成学习(ensembe learning )是机器学习中最先进、最有效、最具有研究价值的领域之一,这类方法会训练多个弱评估器(base estimators)、并将它们输出的结果以某种方式结合起来的问题。
集成学习的一般结构为:先产生一组“个体学习器”,再用某种策略将它们结合起来。集成中只包含同种类型的个体学习器,称为同质,当中的个体学习器亦称为“基学习器”,相应的算法称为“基学习算法”。集成中包含不同类型的个体学习器,称为“异质”,当中的个体学习器称为“组建学习器”。
要获得好的集成,个体学习器应“好而不同”,即个体学习器要有一定的“准确性”,即学习器不能太坏,并且要有多样性,即个体学习器间具有差异。
从今天的眼光来看,集成学习的三个研究领域:
关注强评估器,试图设计出强大的规则来融合强分类器的结果、以获取更好的融合结果。这个领域的手段主要包括了投票法voting,堆叠法stacking,混合法blending等,且被融合的模型需要是强分类器。
主要专注于对传统的机器学习算法的集成,这个领域覆盖大部分我们熟悉的集成算法和集成手段,如装袋法bagging,提升法boosting。这个领域试图设计强大的集成算法、来将多个弱学习器提升称为强学习手段。
常常出现在深度学习领域。将一个复杂的任务拆解成为几个相对简单且更小的子任务,然后针对不同的子任务训练出个体学习器(专家),再结合这些学习器的结果得出的结果得出最终的输出。
“Bagging”又称“装袋法”,并行建立多个弱评估器(通常是决策树,也可以是其他非线性算法),并结合多个弱评估器的结果进行输出。
import numpy as np
import pandas as pd
import sklearn
import matplotlib as mlp
import seaborn as sns
import re,pip,conda
#建立7个弱评估器
r_clf=np.array([0,2,1,1,2,1,0])
b_result_clf=np.argmax(np.bincount(r_clf))
b_result_clf
2.如果是二分类,涉及到有一些负数类别
if (r_clf==1).sum()>(r_clf!=1).sum():
1
else:
-1
r_clf=np.array([1,1,1,-1,-1,-1,-1])
(r_clf==1).sum()#True是1,False是0
(r_clf==-1).sum()
b_result=1 if (r_clf==1).sum()>(r_clf!=1).sum()else -1
b_result
3.如果评估器的数量是偶数,而少数与多数刚好一致怎么办?
r_clf=np.array([1,1,1,0,0,0,2,2])
4.回归的情况,就是求均值
r_reg=np.array([-2.082,-0.601,-1.686,-1.001,-2.037,0.1284,0.8500])
b_result_reg=r_reg.mean()
b_result_reg
-0.9183714285714285
在sklearn中,我们可以接触到两个Bagging集成算法,一个是随机森林,一个是极端随机数,它们都是以决策树为弱评估器的有监督算法,可以被用于分类、回归、排序等各种任务。
构建过程:从提供的数据集中随机抽取出不同的子集,用于建立多棵不同的决策树,并按照bagging的规则对单棵决策树进行集成(回归则平均,分类则少数服从多数。
在sklearn中,随机森林可以实现回归也可以实现分类:
我们可以使用“实例化、fit、predict/score"三部曲来使用随机森林,同时我们也可以使用sklearn中的交叉验证方法来实现随机森林。其中,回归森林的默认评估指标是R2,分类森林的模型评估指标是准确率。
我们运用kaggle上面的房价预测模型对于决策树和随机森林进行评比。
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.tree import DecisionTreeRegressor as DTR
from sklearn.model_selection import cross_validate,KFold
data=pd.read_csv(r"C:\Users\zoutong\Desktop\programming\caicai\集成学习\House Price\train_encode.csv")
data.head()
data.shape
X=data.iloc[:,:-1]
y=data.iloc[:,-1]
y.mean()
这个是y值:
0 208500 1 181500 2 223500 3 140000 4 250000 ... 1455 175000 1456 210000 1457 266500 1458 142125 1459 147500 Name: SalePrice, Length: 1460, dtype: int64 这个是均值:180921.19589041095
可以看出MSE应该很大
reg_f=RFR()
reg_t=DTR()
cv=KFold(n_splits=5,shuffle=True,random_state=1412)#实例化交叉验证方式
result_t=cross_validate(reg_t#进行交叉验证的评估器,
, X,y#数据
,cv=cv#交叉验证模式
,scoring="neg_mean_squared_error"#评估指标
,return_train_score=True#是否返回训练分数
,verbose=True#是否打印进程
,n_jobs=8#线程数,调用资源帮我进行运算
)
result_f=cross_validate(reg_f#进行交叉验证的评估器,
, X,y#数据
,cv=cv#交叉验证模式
,scoring="neg_mean_squared_error"#评估指标
,return_train_score=True#是否返回训练分数
,verbose=True#是否打印进程
,n_jobs=8#线程数,调用资源帮我进行运算
)
##默认是并行增长的,所以即使默认100棵树。
从两个交叉验证时间对比来看,即使随机森林默认是100棵树,决策树就是一棵树,但是它们进行交叉验证的时间都是差不多的,一个2.9s,一个3.4s。因为决策树是并行进行交叉验证的,但是树如果增多,时间也会长。
从test_score和train_score来看,决策树训练误差不大,但是测试误差特别大。所以是超级过拟合,随机森林还好。若用MSE来算的话,也比较大。所以在集成学习中,我们衡量回归类算法的指标一般是RMSE(根均方误差),也就是MSE开根号的结果。因此,如果可以,我们能使用标准差进行模型稳定性的衡量。
sklearn中所有算法都不支持接入更多的计算资源,因此,当我们想要使用随机森林在巨量数据上进行运算,很可能会遭遇到资源短缺的情况。我们由两种方法可以解决这个问题:
增量学习在有监督和无监督学习中都存在。增量学习允许算法不断接入新数据来拓展当前模型,即允许巨量数据被分成若干子集,分别输入模型进行训练。
通常来说,当模型经过一次训练之后,如果再使用新数据对模型进行训练,原始数据训练出来的模型会被替代掉。
过程:对于sklearn自带的加利福尼亚的预测房价数据,使用随机森林进行建模,接着使用本节房价数据X,y训练同一模型,发现随机森林的树不是同一个树了。刚开始加利福尼亚运用model1算出来的均方误差特别小,后来巨大。说明kaggle数据集训练的树完全覆盖原来的树,因此,模型不再有任何预测y_fc的能力了。
from sklearn.datasets import fetch_california_housing
from sklearn.metrics import mean_squared_error
x_fc=fetch_california_housing().data
y_fc=fetch_california_housing().target
model=RFR(n_estimators=3,warm_start=False)#不支持增量学习
model1=model.fit(x_fc,y_fc)
#RMSE
mean_squared_error(y_fc,model.predict(x_fc))**0.5
0.30008047166986423 RMSE特别小
#使用estimators_查看森林中所有树的情况,可以看到每一棵树的随机数种子
model1.estimators_
[DecisionTreeRegressor(max_features=1.0, random_state=1232335128), DecisionTreeRegressor(max_features=1.0, random_state=1411429875), DecisionTreeRegressor(max_features=1.0, random_state=1678287932)]
model1=model1.fit(X.iloc[:,:8],y)
#注意,x由80个特征,x_fc有八个特征,输入同一模型数据必须要结构一致
model.estimators_#新的树代替了原始的树,model1原来的树完全消失了
[DecisionTreeRegressor(max_features=1.0, random_state=764213458), DecisionTreeRegressor(max_features=1.0, random_state=10178065), DecisionTreeRegressor(max_features=1.0, random_state=932275313)]
我们发现原来的树的随机种子完全不同,说明树因为数据的改变而改变。
mean_squared_error(y_fc,model1.predict(x_fc))**0.5
148886.37723575174 RMSE大到离谱,模型不再具有预测y_fc的能力了。
sklearn的覆盖规则是可以进行交叉验证的基础,正是因为每次训练都受到上次训练的影响,我们才可以对模型进行交叉验证,否则就会出现数据泄露的情况。但在增量学习中,原始数据训练的树不会被替代掉,模型会记得之前训练过的数据,我们来看看详细情况:
依然使用相同数据做例子,这一次我们让warm_start参数取值为True,允许随机森林进行增量学习:
model=RFR(n_estimators=3,warm_start=True)#支持增量学习
model2=model.fit(x_fc,y_fc)
#RMSE
mean_squared_error(y_fc,model.predict(x_fc))**0.5
0.29607833257302113
#使用estimators_查看森林中所有树的情况,可以看到每一棵树的随机数种子
model2.estimators_
[DecisionTreeRegressor(max_features=1.0, random_state=1667700164), DecisionTreeRegressor(max_features=1.0, random_state=961174203), DecisionTreeRegressor(max_features=1.0, random_state=1336242472)]
model2=model2.fit(X.iloc[:,:8],y)
#注意,x由80个特征,x_fc有八个特征,输入同一模型数据必须要结构一致
(mean_squared_error(y_fc,model2.predict(x_fc)))**0.5
0.29607833257302113
model2.estimators_#在增量学习中,树没有发生变化
[DecisionTreeRegressor(max_features=1.0, random_state=1667700164), DecisionTreeRegressor(max_features=1.0, random_state=961174203), DecisionTreeRegressor(max_features=1.0, random_state=1336242472)]
树没有变,所以在增量学习中,已经训练过的结果会被保留。对于随机森林这样的Bagging模型来说,这意味着之前的数据训练出来的树会保留,新数据会训练出新的树,新的树和旧的树互不影响。
不过,这里存在一个问题:虽然原来的树没有发生变化,但增量学习看起来并没有增加新的树——事实上,对于随机森林而言,我们需要手动增加新的树:
model2.n_estimators +=2#增加两棵树,用于增量学习
model2
model2.fit(x.iloc[:,:8],y)
model2.estimators_
[DecisionTreeRegressor(max_features=1.0, random_state=1667700164), DecisionTreeRegressor(max_features=1.0, random_state=961174203), DecisionTreeRegressor(max_features=1.0, random_state=1336242472), DecisionTreeRegressor(max_features=1.0, random_state=394505857), DecisionTreeRegressor(max_features=1.0, random_state=419333141)]
原来的树还是没有发生变化,新增的树是基于新输入的数据进行训练的。