热线电话:13121318867

登录
2020-08-28 阅读量: 785
机器学习——集成算法

多个模型集成在一起的模型叫做集成评估器,组成集成评估器的每个模型都叫做基评估器。通常来说,有两类集成算法:装袋法(bagging)、提升法(boosting)


装袋法的核心思想是构建多个相互独立的评估器,然后对其预测进行平均或多数表决原则来决定集成评估器的结果。装袋法的代表模型就是随机森林。

提升法中,基评估器是相关的,是按顺序一一构建的。其核心思想是结合弱评估器的力量一次次对难以评估的样本进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost和梯度提升树。


bagging(装袋法)

又称自主聚集,是一种根据均匀概率分布从数据集中重复抽样(有放回的)的技术。每个新数据集和原始数据集的大小相等。由于新数据集中的每个 样本都是从原始数据集中有放回的随机抽样出来的,所以新数据集中可能有重复的值,而原始数据集中的某些样本可能根本就没出现在新数据集中。


图片.png


有放回的随机抽样

自主采样法(Bootstap sampling),也就是说对于m各样本的原始数据集,每次随机选取一个样本放入采样集,然后把这个样本重新放回原数据集中,然后再进行下一个样本的随机抽样,直到一个采样集中的数量达到m,这样一个采样集就构建好了,然后我们可以重复这个过程,生成n个这样的采样集。也就是说,最后形成的采样集,每个采样集中的样本可能是重复的,也可能原始数据集中的某些样本根本就没抽到,并且每个采样集中的样本分布可能都不一样。


根据有放回的随机抽样构造的n个采样集,我们就可以对它们分别进行训练,得到n个弱分类器,然后根据每个弱分类器返回的结果,我们可以采用一定的组合策略得到我们最后需要的强分类器。


boosting(提升法)

boosting是一个迭代的过程,用来自适应地改变训练样本的分布,使得弱分类器聚焦到那些很难分类的样本上。它的做法是给每一个训练样本赋予一个权重,在每一轮训练结束时自动调整权重。


图片.png


组合策略

1)平均法

对于数值类的回归预测问题,通常使用的结合策略是平均法,也就是说,对于若干个弱学习器的输出进行平均得到最终的预测输出。

最简单的平均是算数平均,也就是说最终预测是

图片.png

如果每个弱分类器有一个权重w,则最终预测是

图片.png


2)投票法

对于分类问题的预测,我们通常使用的是投票法。假设我们的预测类别是 ,对于任意一个
预测样本x,我们的n个弱学习器的预测结果分别是(h1(x),h2(x)...hn(x))。
最简单的投票法是相对多数投票法,也就是我们常说的少数服从多数,也就是n个弱学习器的对样本x的
预测结果中,数量最多的类别ci为最终的分类类别。如果不止一个类别获得最高票,则随机选择一个做
最终类别。
稍微复杂的投票法是绝对多数投票法,也就是我们常说的要票过半数。在相对多数投票法的基础上,不
光要求获得最高票,还要求票过半数。否则会拒绝预测。
更加复杂的是加权投票法,和加权平均法一样,每个弱学习器的分类票数要乘以一个权重,最终将各个
类别的加权票数求和,最大的值对应的类别为最终类别。


随机森林分类器

分类树组成的森林就叫做随机森林分类器,回归树所集成的森林就叫做随机森林回归器。

class sklearn.ensemble.RandomForestClassifier(n_estimators='10',criterion='gini',max_depth=None,min_samples_split=2,min_samples_leaf=1,min_weight_fraction_leaf=0,max_features='auto',max_leaf_nodes=None,min_impurity_decrease=0,min_impurity_split=None,bootstrap=True,oob_score=False,n_jobs=None,random_state=None,verbose=0,warm_start=False,class_weight=None)


重要参数

控制基评估器的参数

criterion:不纯度的衡量指标,有基尼系数和信息熵两种选择

max_depth:树的最大深度,超过最大深度的树枝会被剪掉

min_samples_leaf:一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生

min_samples_split:一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则分枝不会发生

max_features:限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃,默认值为总特征个数开平方取整

min_impurity_decrease:限制信息增益的大小,信息增益小于设定数值的分枝不会发生


单个决策树的准确率越高,随机森林的准确率也会越高,因为装袋法是依赖于平均值或者少数服从多数原则来决定集成的结果的。


1)n_estimators

这是森林中树木的数量,即基评估器的数量。这个参数对随机森林模型的精确性影响是单调的,n_estimators越大,模型的效果往往越好。但是相应的,任何模型都有决策边界,n_estimators达到一定的程度之后,随机森林的精确性往往不再上升或开始波动。


建立一片森林

导包

import matplotlib.pyplot as plt

%matplotlib inline

from sklearn.tree import DecisionTreeClassifier

from sklearn.ensemble import RandomForestClassifier

from sklearn.datasets import load_wine


导入需要的数据集

wine=load_wine()

wine.data

wine.target


sklearn建模的基本流程

#切分训练集和测试集

from sklearn.model_selection import train_test_split

Xtrain,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)


#建立模型

clf=DecisionTreeClassifier(random_state=0)

rfc=RandomForestClassifier(random_state=0)

clf=clf.fit(Xtrain,Ytrain)

rfc=rfc.fit(Xtrain,Ytrain)


#查看模型效果

score_c=clf.score(Xtest,Ytest)

score_r=rfc.score(Xtest,Ytest)


#画出随机森林和决策树在十组交叉验证下的效果对比

rfc_l=[]

clf_l=[]


for i in range(10):

rfc=RandomForestClassifier(n_estimators=25)

rfc_s=cross_val_score(rfc.wine.data,wine.target,cv=10).mean()

rfc_l.append(rfc_s)

clf=DecisionTreeClassifier()

clf_s=cross_val_score(clf,wine.data,wine.target,cv=10).mean()

clf_l.append(clf_s)


#绘制结果曲线

plt.plot(range(1,11),rfc_l,label='RandomForest')

plt.plot(range(1,11),clf_l,label='DecisionTree')

plt.legend()

plt.show()


图片.png

其中,i是判断错误的次数,也是判错的树的数量,ε是一棵树判断错误的概率,(1-ε)是判断正确的概率,共判对25-i次。采用组合,是因为25棵树中,有任意i棵都判断错误。

import numpy as np

from scipy.special import comb

np.array([comb(25,i)*(0.2**i)*((1-0.2)**(25-i)) for i in range(13,26)]).sum()


2)random_state

随机森林中的random_state控制的是生成森林的模式

#随机森林中的random_state控制的是生成森林的模式

rfc=RandomForestClassifier(n_estimators=20,random_state=2)

rfc=rfc.fit(Xtrain,Ytrain)


#随机森林的重要属性之一:estimators,查看森林中树的状况

rfc.estimators_[0].random_state


3) bootstrap&oob_score

袋装法正是通过有放回的随机抽样技术来形成不同的训练数据,bootstrap就是用来控制抽样技术的参数

bootstrap参数默认True,代表采用这种有放回的随机抽样技术。通常,这个参数不会被我们设置为False。

会有约37%的训练数据被浪费掉,没有参与建模,这些数据被称为袋外数据。也就是说,在使用随机森林时,我们可以不划分测试集和训练集,只需要用袋外数据来测试我们的模型即可。如果希望用带外数据来测试,则需要在实例化时就将oob_score这个参数调整为True,训练完毕之后,我们可以用随机森林的另一个重要属性:oob_score_来查看我们的在袋外数据上测试的结果。


#无需划分训练集和测试集

rfc=RandomForestClassifier(n_estimators=25,oob_score=True)

rfc=rfc.fit(wine.data,wine.target)


#重要属性oob_score_

rfc.oob_score_


#重要属性和接口

作为树模型的集成算法,随机森林也有feature_importances_这个属性

随机森林的接口和决策树完全一致,有四个常用接口:apply、fit、predict和score。除此之外,还需要注意随机森林的predict_proba接口,这个接口返回每个测试样本对应的被分到每一类标签的概率,标签有几个分类就返回几个概率。如果是二分类问题,则predict_proba返回的数值大于0.5的,就分为1,小于0.5的,被分为0。传统的随机森林时利用袋装法中的规则,平均或少数服从多数来决定集成的结果,而sklearn中的随机森林是平均每个样本对应的predict_proba返回的概率,得到一个平均概率,从而决定测试样本的分类。


bagging 的另一个必要条件:基分类器的判断准确率至少要超过随机分类器,基分类器的判断准确率至少要超过50%。


随机森林回归器

class sklearn.ensemble.RandomForestRegressor(n_estimators='warn',criterion='mse',max_depth=None,min_samples_split=2,min_samples_leaf=1,min_weight_fraction_leaf=0,max_features='auto',max_leaf_nodes=None,min_impurity_decrease=0,min_impurity_split=None,bootstrap=True,oob_score=False,n_jobs=None,random_state=None,verbose=0,warm_start=False)


重要参数,属性与接口

criterion:回归树衡量分枝质量的指标,支持的标准有三种:

1)输入“mse”使用均方误差,父节点和叶子节点之间的均方误差的差额将被用来作为特征选择的标准,这种方法通过使用叶子节点的均值来最小化L2损失。


2)输入“friedman_mse”使用费尔德曼均方误差,这种指标使用费尔德曼针对潜在分枝中的问题改进后的均方误差。


3)输入“mae”使用绝对平方误差MAE,这种指标使用叶节点的中值来最小化L1损失


图片.png


其中N是样本数量,i是每一个数据样本,fi是模型回归出的数值,yi是样本点i实际的数值标签,所以MSE的本质,其实是样本真实数据与回归结果的差异。在回归树中,MSE不只是我们的分枝质量衡量指标,也是我们最常用的衡量回归树回归质量的指标,当我们使用交叉验证,或者其他方式获取回归树的结果时,我们往往选择均方误差作为我们的评估(在分类树中这个指标是score代表的预测准确率)。


回归树的接口score返回的是R平方,并不是MSE。

图片.png

其中u是残差平方和(MSE*N),v是总平方和,N是样本数量,i是每一个数据样本,fi是模型回归出的数值,yi是样本点i实际的数值标签。图片.png 是真实数值标签的平均数。R2可以为正为负(如果模型的残差平方和远远大于模型的总平方和,模型非常糟糕,R2就会为负),而均方误差永远为正。


虽然均方误差永远为正,但是sklearn当中使用均方误差作为评判标准时,却是计算“负均方误差”(neg_mean_squared_error),因为被sklearn划分为模型的一种损失,在sklearn当中都以负数表示。真正的均方误差MSE的数值,其实就是neg_mean_squared_error去掉负号的数字。


from sklearn.datasets import load_boston

from sklearn.model_selection import cross_val_score

from sklearn.ensemble import RandomForestRegressor


boston=load_boston()

regressor=RandomForestRegressor(n_estimators=100,random_state=0)

cross_val_score(regressor,boston.data,boston.target,cv=10,scoring='neg_mean_squared_error')


#查看所有可以用的评估指标

sorted(sklearn.metrics.SCORERS.keys())


Adaboost的Scikit-learn实现

AdaBoost 自适应增强的缩写,它的自适应在于:前一个基本分类器分错的样本会得到加强(也就是得到更高的权重),加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个 预定的足够小的错误率或达到预先指定的最大迭代次数,算法停止。


具体来说,整个Adaboost迭代算法就3步:

1)初始化训练数据的权重

如果有N个样本,则每一个样本最开始时都被赋予相同的权值:1/N

2)训练弱分类器

具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。

3)将各个训练得到的弱分类器组合成强分类器

各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。


Scikit-Learn中AdaBoost类库比较直接,就是AdaBoostClassifier和AdaBoostRegressor两个,AdaBoostClassifier用于分类,AdaBoostRegressor用于回归。


当我们对Adaboost调参时,主要对两部分内容进行调参,第一部分是对我们的Adaboost的框架进行调参,第二部分是对我们选择的弱分类器进行调参。


  1. AdaBoost分类器

    class sklearn.ensemble.AdaBoostClassifier(base_estimator=None,n_estimators=50,learning_rate=1.0,algorithm='SAMME.R',random_state=None)


核心参数

base_estimator:None或输入字符串,默认为None,即我们的弱分类器,理论上可以选择任何一个分类学习器,不过需要支持样本权重。我们常用的一般是CART决策树或者神经网络MLP,如果为None,则弱分类器为DecisionTreeClassifier(max_depth=1)


n_estimators:整数,默认为50。弱学习器的最大迭代次数,或者说最大的弱学习器的个数。一般来说n_estimators太小,容易欠拟合,n_estimators太大,又容易过拟合,一般选择一个适中的数值。默认是50,在实际调参的过程中,我们常常将n_estimators和参数learning_rate一起考虑。


learning_rate:浮点数,默认为1。即每个弱学习器的权重缩减系数。对于同样的训练集拟合效果,较小的权重缩减系数意味着我们需要更多的弱学习器的迭代次数。


algorithm:可选择{‘SAMME’,‘SAMME.R’},默认是‘SAMME.R’。scikit-learn实现了两种Adaboost分类算法,SAMME和SAMME.R。两者的主要区别是弱学习器权重的度量,SAMME使用了对样本集分类效果作为弱学习器权重,而SAMME.R使用了对样本集分类的预测概率大小作为弱学习器权重


random_state:整数,sklearn中设定好的RandomState实例,或None,可不填,默认为None

输入整数,random_state是随机数生成器生成的随机数种子

输入RandomState实例,则random_state是一个随机数生成器

输入None,随机数生成器会是np.random模块中的RandomState实例


弱学习器参数

图片.png


import numpy as np

import matplotlib.pyplot as plt

%matplotlib inline

from sklearn.ensemble import AdaBoostClassifier

from sklearn.tree import DecisionTreeClassifier

from sklearn.datasets import make_gaussian_quantiles


x1,y1=make_gaussian_quantiles(cov=2,n_samples=500,n_features=2,n_classes=2,random_state=1)

x2,y2=make_gaussian_quantiles(mean=(3,3),cov=1.5,n_samples=400,n_features=2.n_classes=2,random_state=1)


X=np.concatenate((x1,x2))

y=np.comcatenate((y1,-y2+1))


#我们通过可视化看看我们的分类数据,它有两个特征,两个输出类别,用颜色区别

plt.scatter(X[:,0],X[:,1],marker='o',c=y)


bdt=AdaBoostClassifier(DecisionTreeClassifier(max_depth=2,min_samples_split=20,min_samples_leaf=5),algorithm='SAMME',n_estimators=200,learning_rate=0.8)

bdt.fit(x,y)


AdaBoost回归器

图片.png


import numpy as np

import matplotlib.pyplot as plt

from sklearn.tree import DecisionTreeRegressor

from sklearn.ensemble import AdaBoostRegressor


rng=np.random.RandomState(1)

X=np.linspace(0,6,100).reshape(-1,1)

y=np.sin(X).ravel()+np.sin(6*X).ravel()+rng.normal(0,0.1,X.shape[0])


regr_2=AdaBoostRegressor(DecisionTreeRegressor(max_depth=4),n_estimators=300,random_state=rng)


regr_2.fit(X,y)

y_2=regr_2.predict(x)


plt.figure()

plt.scatter(X,y,c='k',label='training samples')

plt.plot(X,y_2,c='r',label='ABR',linewidth=2)

plt.xlabel('data')

plt.ylabel('target')

plt.title('Boosted Decision Tree Regression')

plt.legend()

plt.show()


图片.png

一个集成模型(f)在未知数据集(D)上的泛化误差E(f;D),由方差(var),偏差(bais)和噪声(ε)共同决定。

偏差:模型的预测值与真实值之间的差异,即每一个红点到蓝线的距离。在集成算法中,每个基评估器都会有自己的偏差,集成评估器的偏差是所有基评估器偏差的均值,模型越精确,偏差越低。


方差:反映的是模型每一次输出结果与模型预测值的平均水平之间的误差,衡量模型的稳定性。模型越稳定,方差越低。


随机森林调参实例

from sklearn.datasets import load_breast_cancer

from sklearn.ensemble import RandomForestClassifier

from sklearn.model_selection import GridSearchCV

from sklearn.model_selection import cross_val_score

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np


data=load_breast_cancer()


rfc=RandomForestClassifier(n_estimators=100,random_state=90)

score_pre=cross_val_score(rfc,data.data,data.target,cv=10).mean()


score_pre


param_grid={'max_depth':np.arange(1,20,1)}

rfc=RandomForestClassifier(n_estimators=39,random_state=90)

GS=GridSearchCV(rfc,param_grid,cv=10)

GS.fit(data.data,data.target)


GS.best_params_

GS.best_score_

















35.3721
0
关注作者
收藏
评论(0)

发表评论

暂无数据