集成学习基础与实战
学习目标
- 理解了解什么是集成学习
- 如何利用随机森林算法建模
- 知道Bagging的集成原理
- 随机森林算法Sklearn关键API实战
1. 为什么学习集成学习
单颗决策树算法容易产生过拟合,所以我们提出集成学习,其中的随机森林算法,可以通过多棵树的方案解决单颗树的过拟合问题,解决实际工作中常见分类问题。
2. 什么是集成学习
传统机器学习算法 (例如:决策树,逻辑回归等) 的目标都是寻找一个最优分类器尽可能的将训练数据分开。集成学习 (Ensemble Learning) 算法的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。集成算法可以说从一方面验证了中国的一句老话:三个臭皮匠,赛过诸葛亮
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AE8ftF2A-1631279319172)(images/2021-1.png)]
集成学习通过建立几个模型来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成组合预测,因此优于任何一个单分类的做出预测。
集成算法大致可以分为:Bagging,Boosting和Stacking等类型。
3. 集成学习分类的串行和并行学习算法
集成学习算法一般分为:bagging、boosting和Stacking。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8E6fIFCJ-1631279319174)(./images/2021-2.png)]
随机森林是集成模型中的一种,常言道:“一个篱笆三个桩,一个好汉三个帮”。集成分类模型便是综合考量多个分类器的预测结果,从而做出决策,集成学习分两种:
(1)利用相同的训练数据同时搭建多个独立的分类模型,然后通过投票的方式,以少数服从多数的原则做出最终的分类决策。今天学习的Bagging(随机森林)算法就是这种方式,即在相同训练数据上同时搭建多颗决策树。
在决策树中学到过一颗标准的决策树是根据每维特征对预测结果的影响程度进行排序,进而决定不同特征从上到下构建分裂节点的顺序;如果这里还按照这种方式随机森林会因为这一策略影响而构建的所有树都一致,从而丧失了多样性。因此随机森林在构建的过程中,每一颗决策树都会放弃这一个固定的算法,转而随机选取特征。
(2)按一定的次序搭建多个分类模型。这些模型之间彼此存在依赖关系。一般后一个模型的加入都需要对现有的集成模型有一定贡献,进而不断提高更新过后的集成模型性能,并借助多个弱分类器搭建出强分类器。代表有Boosting(AdaBoost)算法。该算法与第一种的随机森林主要区别在于每一颗决策树在生成的过程中都会尽可能降低模型在训练集上的拟合或训练误差。
3.1 集成学习关键要素
俗话说:“三个臭皮匠赛过诸葛亮”。
当使用某一种分类器不能使我们达到很好的效果的时候,我们不妨设想将这些分类效果不好的分类器组合一下,再去看看效果是否有提升,这就是集成学习的思想。
集成算法(Ensemble Learning)思想:通过构建并结合多个学习器来完成学习任务,有时候我们也叫作“多分类器系统”。如下图C1,C2都是某一种个体的分类器,我们采用某种策略将他们组合起来。
我们有10个分类器,多数表决如下图,其中三角形、正方形或圆分别代表一个类别。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5A5doGza-1631279319176)(./images/2021-3.png)]
个体的分类器由一个现有的学习算法从训练数据产生,例如:C4.5决策树算法,我们一般把个体分类器全部为同种的分类器称为“同质的”,如全部为决策树模型。同质的集成学习中的个体学习器称为“基学习器(base learner)”,相应的算法称为基学习算法。反之,集成中包含不同种的学习器,我们称之为“异质”的,异质集成中的个体学习器包含不同的学习算法组成的,这种情况下的学习器称为“组合学习器”。相信这些名词大家能够了解。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GetDiYPv-1631279319177)(./images/2021-4.png)]
? 图1: 集成学习的系统示意图
集成学习通过将多个学习器组合,常获得比单一学习器显著优越的泛化性能。这对弱学习器特别明显,这里的弱学习器我们一般会使用决策树,BP神经网络和逻辑回归,有时候SVM也可以作为个体学习器。
下图是使用多数投票法通用集成方法的概念:
3.2 集成学习器性能评估
一般经验中如果把好坏不等的东西掺到一起,通常结果会比最坏的好一些,比最好的坏一些。集成学习把多个学习器结合起来,如何获得比最好的单一学习器更好的性能呢?
考虑一个例子:二分类问题中,假定三个分类器在三个测试样本上表现,如下图所示。打对勾的表示正确分类,打叉号的表示分类错误。集成学习的结果通过投票法voting产生。即少数服从多数。第一个图中每个分类器有66.6%的精度,但集成学习却达到了100%。第二个图中三个分类器没有差别,但是集成之后性能却没有什么提高。第三幅图中每个分类器的精度都只有33.3%,集成学习的结果更糟糕。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGnPkrnS-1631279319179)(./images/2021-6.png)]
这个例子我们可以总结出:要获得好的集成,个体学习器应有一定的准确性,即学习器不能太坏,并且要有“多样性”,即学习器之间具有差异。
4. 集成学习分类之Bagging算法
Bagging (Boostrap Aggregating) 是由 Breiman 于 1996 年提出。
4.1 Bootstrap sampling自助采样
之前的课程已经讲过模型的评估方法中有留一法(将数据集划分为两个互不相交的集合,一个做测试集,一个做训练集)和交叉验证方法(将数据分成k个大小相似互不相交的子集,每次使用k-1个子集做训练集,剩下的一个子集做测试集,以此循环进行k次的训练和测试,最后返回k次测试结果的均值。)。但是上述两种方法中都保留了一部分样本用于测试,所以实际模型所使用的训练集比源数据都要小,因此就会引入一些因训练样本规模不同而导致的估计偏差。另外一方面留一法受训练样本影响较小,但是计算复杂度又太高。因此为了解决减少训练样本规模不同造成的影响,同时还能比较高效地进行测试集的评估。自助法就是很好的解决方案。
booststrap抽样
在样本集D(样本数为m)内有放回的抽样,抽取数为m,每次抽取的概率相等为1/m,可能重复抽取。我们做一个简单的估计,样本m次采样中不被采样的概率为
**取极限得到原数据集D中36.8%的样本没有出现在采样数据集D1中。**我们可以使用D1作为训练集,D-D1作为测试集。这样实际评估的模型与期望的模型都使用m个训练样本,而我们仍有数据总量的1/3的,没有在训练集中出现的样本用于测试。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F6yltqLb-1631279319180)(./images/2021-8.png)]
4.2 Bagging算法
此算法没有使用相同的训练集拟合集成分类器中的单个分类器,而是采用了Bootstrap有放回抽样选取训练数据集。
下图有7个不同的训练样例,每一轮的bagging循环中,样本数据均可放回随机抽样,每个bootstrip抽样都是被用于分类器C的训练,这就是一颗典型的未剪枝的决策树。
随机森林是bagging的特例,它使用了随机特征子集去拟合单颗决策树。
4.3 算法流程
Bagging基本流程:通过上述自助采样,采出T个含m个训练样本的采样集,然后基于每个采样集训练出一个基学习器,在将这些基学习器进行组合。
在对预测输出进行结合的时候,Bagging通常对分类任务使用简单投票法,对回归任务进行简单的平均法。但是如果投票个数一致,则最简单的做法是随机选择一个类别,当然也可以进一步考察学习器投票的置信度来确定最终的分类。
案例:把下面的圈和方块进行分类
4.4 算法图解分析
基本分类器可以是决策树,逻辑回归等基分类器。
对于稳定性不好的分类器很实用,通过多数投票,减小了泛化误差,而对于稳定的分类器,集成效果并不明显。
4.5 Bagging性能
(1)Bagging是一个很高效的集成学习算法
(2)Bagging与下面讲的AdaBoost只适用于二分类不同,它能不经修改地用于多分类、回归任务。
(3)自助bootstrap采样过程还给Bagging带来了另一个优点:由于每个基学习器只使用了初始训练集中约63.2%的样本,剩下的约36.8%样本可用作验证集来泛化性能进行“包外样本评估(即:不同于训练数据的样本)”。
(4)从偏差-方差分解角度看,Bagging主要关注降低方差,因此它在不剪枝决策树、神经网络等易受样本扰动的学习器上效果更为明显。
4.6 Bagging算法总结
Bagging算法首先采用M轮自助采样法,获得M个包含N个训练样本的采样集。然后,基于这些采样集训练出一个基学习器。最后将这M个基学习器进行组合。组合策略为:
- 分类任务采用简单投票法:即每个基学习器一票
- 回归问题使用简单平均法:即每个基学习器的预测值取平均值。
5. 集成学习分类之随机森林算法详解
随机森林就是建立很多决策树,组成一个决策树的“森林”,通过多棵树投票来进行决策。这种方法能够有效地提高对新样本的分类准确度。
随机森林在以决策树为基学习器构建Bagging集成(样本的随机选取)的基础上,进一步在决策树的训练过程中引入随机属性选择。具体来说,传统决策树在选择划分属性时是在当前节点的属性集合(假设有d个属性)中选择一个最优属性;而在RF随机森林中,对基决策树的每个节点,先从该节点的属性集合中随机选择一个包含K个属性的子集,然后在从这个子集中选择一个最优属性用于划分。K=d就是传统决策树,K=1则是随机选取一个属性用于划分,一般情况
5.1 集成学习分类之随机森林的步骤
如上图:
首先,对样本数据进行有放回的抽样,得到多个样本集。具体来讲就是每次从原来的N个训练样本中有放回地随机抽取N个样本(包括可能重复样本)。
然后,从候选的特征中随机抽取m个特征,作为当前节点下决策的备选特征,从这些特征中选择最好地划分训练样本的特征。用每个样本集作为训练样本构造决策树。单个决策树在产生样本集和确定特征后,使用CART算法计算,不剪枝。
最后,得到所需数目的决策树后,随机森林方法对这些树的输出进行投票,以得票最多的类作为随机森林的决策。
说明:
(1)随机森林的方法即对训练样本进行了采样,又对特征进行了采样,充分保证了所构建的每个树之间的独立性,使得投票结果更准确。
(2)随机森林的随机性体现在每棵树的训练样本是随机的,树中每个节点的分裂属性也是随机选择的。有了这2个随机因素,即使每棵决策树没有进行剪枝,随机森林也不会产生过拟合的现象。
随机森林中有两个可控制参数:
- 森林中树的数量(一般选取值较大)
- 抽取的属性值m的大小。
思考
- 为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样。
- 为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。
5.2 随机森林的特点总结
随机森林简单、容易实现、计算开销小,被誉为“代表集成学习计数水平的方法”。可以看出随机森林只是对Bagging做了很小的改动。Bagging的多样性只是体现在样本的随机性,随机森林的基学习器的多样性不仅来自于样本的随机性,还来自于属性的随机性。随机森林随着学习器数目的增加,随机森林通常会收敛到更低的泛化误差。
(1)分类结果更加准确
(2)可以处理高维度的属性,并且不用做特征选择
(3)即使有很大部分数据遗失,仍可以维持高准确度
(4)学习过程快速
(5)在训练完成后,能够给出哪些属性比较重要
(6)容易实现并行化计算
(7)在训练过程中,能够检测到属性之间的相互影响
5.3 随机森林的API
http://scikit-learn.org/0.17/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble.RandomForestClassifier
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhWstP1n-1631279319181)(./images/wpswnkqj4.png)]
反应随机性的参数:
方法:
5.4 随机森林的Sklearn实战
这里使用泰坦尼克号案例实战:
import pandas as pd
titanic=pd.read_csv("data/titanic.csv")
titanic.info()
X=titanic[['pclass','age','sex']]
y=titanic['survived']
X['age'].fillna(X['age'].mean(),inplace=True)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test =train_test_split(X,y,test_size=0.25,random_state=22)
from sklearn.feature_extraction import DictVectorizer
vec=DictVectorizer(sparse=False)
X_train=vec.fit_transform(X_train.to_dict(orient='records'))
X_test=vec.transform(X_test.to_dict(orient='records'))
from sklearn.tree import DecisionTreeClassifier
dtc=DecisionTreeClassifier()
dtc.fit(X_train,y_train)
dtc_y_pred=dtc.predict(X_test)
dtc.score(X_test,y_test)
from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(max_depth=8,random_state=9)
rfc.fit(X_train,y_train)
rfc_y_pred=rfc.predict(X_test)
rfc.score(X_test,y_test)
from sklearn.metrics import classification_report
print("dtc_report:",classification_report(dtc_y_pred,y_test))
print("rfc_report:",classification_report(rfc_y_pred,y_test))
超参数选择代码:
rf = RandomForestClassifier()
param={"n_estimators":[80,100,200], "max_depth": [2,4,6,8,10,12],"random_state":[9]}
from sklearn.model_selection import GridSearchCV
gc = GridSearchCV(rf, param_grid=param, cv=2)
gc.fit(X_train, y_train)
print("随机森林预测的准确率为:", gc.score(X_test, y_test))
5.5 总结
Bagging + 决策树/线性回归/逻辑回归/深度学习… = bagging集成学习方法
经过上面方式组成的集成学习方法:
- 均可在原有算法上提高约2%左右的泛化正确率
- 简单, 方便, 通用
6. Boosting框架简介
6.1 算法机制
Boosting是一组可将弱学习器升为强学习器算法。这类算法的工作机制类似:
1.先从初始训练集训练出一个基学习器
2.在根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续得到最大的关注。
3.然后基于调整后的样本分布来训练下一个基学习器;
4.如此重复进行,直至基学习器数目达到实现指定的值T为止。
5.再将这T个基学习器进行加权结合得到集成学习器。
简而言之:每新加入一个弱学习器,整体能力就会得到提升
Boosting算法的著名代表就是Adaboost算法。
因此,对于Boosting算法,存在两个问题:
- 在每一轮中如何调整训练集,使训练的弱分类器得以进行;(调整样本权值)
- 如何将各个弱分类器联合起来形成强分类器。 (调整模型权值)
6.2 提升的概念强化
提升Boosting是一个机器学习技术,可以用于回归和分类问题,它每一步产生一个弱预测模型(如决策树)并加权累加到总模型中;如果每一步的弱预测模型生成都是依据损失函数的梯度方向,则称之为梯度提升(GradientBoosting)。
梯度提升算法首先给定一个目标损失函数,它的定义域是所有可行的弱函数集合(基函数);提升算法通过迭代的选择一个负梯度方向上的基函数来逐渐逼近局部极小值。这种在函数域的梯度提升观点对机器学习有很大影响。
提升的理论意义:如果一个问题存在弱分类器,则可以通过提升的办法得到强分类器。
6.3 Boosting实现过程
如下过程演示:
7. 集成学习分类之Adaboost算法原理及实战
Adaptive Boosting称之为自适应boosting,利用该学习器可以提高学习器的性能。
7.1 AdaBoost简介
AdaBoost自适应提升学习算法和Boosting考虑的点一样
Adaboost自适应在于:“关注”被错分的样本,“器重”性能好的弱分类器:(观察下图)
(1)不同的训练集—>调整样本权重
(2)“关注”—>增加错分样本权重
(3)“器重”—>好的分类器权重大
(4) 样本权重间接影响分类器权重
AdaBoost算法的两个核心步骤:
**权值调整:**AdaBoost算法提高那些被前一轮基分类器错误分类样本的权值,而降低那些被正确分类样本的权值。从而使得那些没有得到正确分类的样本,由于权值的加大而受到后一轮基分类器的更大关注。
基**分类器组合:**AdaBoost采用加权多数表决的方法。
- 加大分类误差率较小的弱分类器的权值,使得它在表决中起到较大的作用。
- 减小分类误差率较大的弱分类器的权值,使得它在表决中起较小的作用。
7.2 AdaBoost特点
AdaBoost把多个不同的弱分类算法,用一种非随机的方式组合起来,表现出惊人的性能。
1,可以使用各种方法构建子分类器,Adaboost算法提供的是框架;
2,子分类器容易构造;
3,速度快,且基本不用调参数;
4,泛化错误率低。
7.3 AdaBoost步骤
Adaboost迭代算法有3步:
1.初始化训练数据的权值分布:假设有N个样本,每个样本赋予相同权值1/N。
2.训练弱分类器:本轮训练中,若某样本分错,则提高它的权值,相反分类正确的样本被降低权值。然后,权值更新过的全体样本被用于训练下一个分类器,使得下一个分类器更关注权重大的难分样本。多次迭代,训练多个弱分类器。
3.加权组合弱分类器:加大分类误差率小的弱分类器的权重,使其在最终表决中起较大作用,而降低分类误差率大的弱分类器的权重,使其在最终表决中起较小作用。
详细步骤举例:
AdaBoost和Boosting不同,AdaBoost使用了整个训练集来训练学习器,其中每个训练样本在每次迭代中都会重新被赋值一个权重,在上一弱学习器错误的基础上进行学习进而构建一个更加强大的分类器。下图1代表了一个2类别问题的训练集,其中所有的样本都被赋予了相同的权重,基于此训练集我们得到了一颗单层决策树,图中的虚线表示,它尝试通过最小代价函数(或决策树的不纯度)划分两类样本(三角形或圆形)。
在下一轮中,图2,我们为前面无分类的样本(圆形)赋予了更大的权重,此外,我们还降低了被正确分类的权重,图2错误的划分了圆形类的三个样本。被分错的样本在第三轮Bossting中,被赋予了更大的权重。
假定AdaBoost只包含了3轮的Boosting过程没我们就能够用加权投票方式将不同重采样训练子集上得到的三个弱学习器进行组合,也就是图4(加权组合弱分类器)。
7.4 算法总结及推广到多维
方法:加大前一轮分错样本权值,减小分对样本权值。而在下一轮迭代中,
总是选取让误差率最低的阈值来设计基本分类器,所以误差率e不断降低,在最终的加权投票时的基分类器的权重也相应的增加。
接下来讨论多维数据的单层决策树分类器构建方法
前面的例子:给定10个一维样本数据及类别。
1.选某个阈值进行分类(即单节点决策树):阈值的一边取+1,另一边取-1,并计算分类误差率;
2.多个不同阈值下分类后,选分类误差率最小的阈值作为本轮的基分类器。
推广到多维数据:
例子中的一维样本数据相当于多维数据中的某个特征向量。
对于多维训练数据,构建单节点决策树时,需要遍历每个特征,最终选择使分类误差率e最小的阈值作为最终分类决策函数。
7.5 AdaBoost实战葡萄酒数据
7.5.1导入数据
import pandas as pd
df_wine = pd.read_csv('data/wine.data')
df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols',
'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',
'Proline']
df_wine = df_wine[df_wine['Class label'] != 1]
X = df_wine[['Alcohol', 'Hue']].values
y = df_wine['Class label'].values
7.5.2 切分数据
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
le = LabelEncoder()
y = le.fit_transform(y)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.4,random_state=1)
7.5.3 在500棵单层决策树上训练AdaBoost
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
tree = DecisionTreeClassifier(criterion='entropy',max_depth=1,random_state=0)
ada= AdaBoostClassifier(base_estimator=tree,n_estimators=500,learning_rate=0.1,random_state=0)
7.5.4 AdaBoost分类器性能评估
from sklearn.metrics import accuracy_score
tree = tree.fit(X_train,y_train)
y_train_pred = tree.predict(X_train)
y_test_pred = tree.predict(X_test)
tree_train = accuracy_score(y_train,y_train_pred)
tree_test = accuracy_score(y_test,y_test_pred)
print('Decision tree train/test accuracies %.3f/%.3f' % (tree_train,tree_test))
ada = ada.fit(X_train,y_train)
y_train_pred = ada.predict(X_train)
y_test_pred = ada.predict(X_test)
ada_train = accuracy_score(y_train,y_train_pred)
ada_test = accuracy_score(y_test,y_test_pred)
print('Adaboost train/test accuracies %.3f/%.3f' % (ada_train,ada_test))
总结:AdaBosst预测准确了所有的训练集类标,与单层决策树相比,它在测试机上表现稍微好一些。单决策树对于训练数据过拟合的程度更加严重一些。总之,我们可以发现Adaboost分类器能够些许提高分类器性能,并且与bagging分类器的准确率接近.
7.5.5 绘制决策区域形状(可以复制演示)
import numpy as np
import matplotlib.pyplot as plt
x_min,x_max = X_train[:,0].min() - 1,X_train[:,0].max() + 1
y_min,y_max = X_train[:,1].min() - 1,X_train[:,1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min,x_max,0.1),np.arange(y_min,y_max,0.1))
f,axarr = plt.subplots(1,2,sharex='col',sharey='row',figsize=(8,3))
for idx,clf,tt in zip([0,1],[tree,ada],['Decision Tree', 'AdaBoost']):
clf.fit(X_train,y_train)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
axarr[idx].contourf(xx,yy,Z,alpha = 0.3)
axarr[idx].scatter(X_train[y_train==0,0],X_train[y_train==0,1],c='blue',marker='^')
axarr[idx].scatter(X_train[y_train==1,0],X_train[y_train==1,1],c='red',marker='o')
axarr[idx].set_title(tt)
axarr[0].set_ylabel('Alcohol', fontsize=12)
plt.text(10.2,-1.2,s='Hue',ha='center',va='center',fontsize = 12)
plt.tight_layout()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gNXtpoEI-1631279319182)(./images/wpskOsnuM.png)]
总结:通过观察区域,我们可以看到AdaBosst的决策区域比单层的决策区域更加复杂。
7.5.6 总结
集成技术与单独的分类器性能比较,集成学习提高了复杂度,但在实践中,需要衡量是否愿意为适度提高预测性能付出更多的计算成本。
8. GBDT梯度提升决策树算法原理及实战
8.1 基础案例演示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kHivfcm7-1631279319183)(./images/image-20210701201818884.png)]
8.2 CART回归树
首先,GBDT使用的决策树是CART回归树,无论是处理回归问题还是二分类以及多分类,GBDT使用的决策树通通都是都是CART回归树。
为什么不用CART分类树呢?
答案:因为GBDT每次迭代要拟合的是梯度值,是连续值所以要用回归树。
分类树和回归树区别?
答案:(1)对于回归树算法来说最重要的是寻找最佳的划分点,那么回归树中的可划分点包含了所有特征的所有可取的值。
(2)在分类树中最佳划分点的判别标准是熵或者基尼系数,都是用纯度来衡量的,但是在回归树中的样本标签是连续数值,所以再使用熵之类的指标不再合适,**取而代之的是平方误差,**它能很好的评判拟合程度。
如下图所示:左侧为决策树回归的图形,下图右侧就是上图对应的数据展示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TsUQ8gTq-1631279319183)(./images/image-20210701202024740.png)]
8.3 GBDT原理简介
基本原理:
① 训练一个模型m1,产生错误e1
② 针对e1训练第二个模型m2,产生错误e2
③ 针对e2训练第三个模型m3,产生错误e3 …
④ 最终预测结果是:m1+m2+m3+…
GBDT是boosting的一种方法,主要思想:
每一次建立单个分类器时,是在之前建立的模型的损失函数的梯度下降方向。
损失函数越大,说明模型越容易出错,如果我们的模型能让损失函数持续的下降,则说明我们的模型在持续不断的改进,而最好的方式就是让损失函数在其梯度的方向上下降。
GBDT的核心在于每一棵树学的是之前所有树结论和的残差
残差就是真实值与预测值的差值
为了得到残差,GBDT中的树全部是回归树,不用分类树
Shrinkage(缩减)是 GBDT 的一个重要演进分支
Shrinkage的思想在于每次走一小步来逼近真实的结果,比直接迈大步的方式好
Shrinkage可以有效减少过拟合的风险。它认为每棵树只学到了一小部分,累加的时候只累加这一小部分,通过多学习几棵树来弥补不足。这累加的一小部分(步长*残差)来逐步逼近目标,所以各个树的残差是渐变的而不是陡变的。
GBDT可以用于回归问题(线性和非线性),也可用于分类问题
8.4 GBDT在Sklearn实战
8.4.1 GBDT的API详解
注意:
损失函数:
偏差,是用于回归问题的平方误差损失函数L(y,y1)=(y-y1)^2
指数损失,用于分类问题L(y,y1)=e^(-y*y1)
官网API:https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html#sklearn.ensemble.GradientBoostingClassifier
解释:
GB 以向前的阶段性方式构建了一个加法模型; 它允许优化任意可微损失函数。 在每个阶段,n_classes_回归树拟合二项式或多项式偏差损失函数的负梯度。 二元分类是一种特殊情况,其中仅引入单个回归树。
8.4.2 泰坦尼克号案例实战
该案例是在随机森林的基础上修改的,可以对比讲解。
数据地址:
http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt
8.4.2.1 导包并选取特征
import pandas as pd
titanic=pd.read_csv("data/titanic.csv")
titanic.info()
X=titanic[['pclass','age','sex']]
y=titanic['survived']
X['age'].fillna(X['age'].mean(),inplace=True)
8.4.2.2 切分数据及特征处理
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test =train_test_split(X,y,test_size=0.25,random_state=22)
from sklearn.feature_extraction import DictVectorizer
vec=DictVectorizer(sparse=False)
X_train=vec.fit_transform(X_train.to_dict(orient='records'))
X_test=vec.transform(X_test.to_dict(orient='records'))
8.4.2.3 三种分类器训练及预测
from sklearn.tree import DecisionTreeClassifier
dtc=DecisionTreeClassifier()
dtc.fit(X_train,y_train)
dtc_y_pred=dtc.predict(X_test)
print("score",dtc.score(X_test,y_test))
from sklearn.ensemble import RandomForestClassifier
rfc=RandomForestClassifier(random_state=9)
rfc.fit(X_train,y_train)
rfc_y_pred=rfc.predict(X_test)
print("score:forest",rfc.score(X_test,y_test))
from sklearn.ensemble import GradientBoostingClassifier
gbc=GradientBoostingClassifier()
gbc.fit(X_train,y_train)
gbc_y_pred=gbc.predict(X_test)
print("score:GradientBoosting",gbc.score(X_test,y_test))
8.4.2.4 三种分类器性能评估
from sklearn.metrics import classification_report
print("dtc_report:",classification_report(dtc_y_pred,y_test))
print("rfc_report:",classification_report(rfc_y_pred,y_test))
print("gbc_report:",classification_report(gbc_y_pred,y_test))
9. 集成算法多样性
集成学习中,个体学习器多样性越大越好。通常为了增大个体学习器的多样性,在学习过程中引入随机性。常用的方法包括:对数据样本进行扰动、对输入属性进行扰动、对算法参数进行扰动。
9.1 数据样本扰动
给定数据集,可以使用采样法从中产生出不同的数据子集。然后在利用不同的数据子集训练出不同的个体学习器。
该方法简单有效,使用广泛。
(1)数据样本扰动对于“不稳定学习器”很有效。“不稳定学习器”是这样一类学习器:训练样本稍加变化就会导致学习器有显著的变动,如决策树和神经网络等。
(2)数据样本扰动对于“稳定学习器”无效。“稳定学习器”是这样一类学习器:学习器对于数据样本的扰动不敏感,如线性学习器、支持向量机、朴素贝叶斯、K近邻学习器等。
如Bagging算法就是利用Bootstrip抽样完成对数据样本的自助采样。
9.2 输入属性的扰动
训练样本通常由一组属性描述,可以基于这些属性的不同组合产生不同的数据子集,然后在利用这些数据子集训练出不同的个体学习器。
(1)若数据包含了大量冗余的属性,则输入属性扰动效果较好。此时不仅训练出了多样性大的个体,还会因为属性数量的减少而大幅节省时间开销。同时由于冗余属性多,即使减少一些属性,训练个体学习器也不会很差。
(2)若数据值包含少量属性,则不宜采用输入属性扰动法。
9.3 算法参数的扰动
通常可以通过随机设置不用的参数,比如对模型参数加入小范围的随机扰动,从而产生差别较大的个体学习器。
在使用交叉验证法(GridSearch网格搜索)来确定基学习器的参数时,实际上就是用不同的参数训练出来了多个学习器,然后从中挑选出效果最好的学习器。集成学习相当于将所有这些学习器利用起来了。
随机森林学习器就结合了数据样本的扰动及输入属性的扰动。
|