参考资料:《速通机器学习》北大博士后AI卢菁
因为原文公式全部炸了,难以阅读,故在学习过程中编写了此笔记,精简了原文并添加了一定自己的理解(所以会有很多不严谨的地方),如有错误感谢指出。
文章目录
第七章 集成学习
7.1 决策树
在决策树中,我们会依次判断各个特征是否满足预设条件,得到最终的决策结果。非叶子节点选择一个特征进行决策,这个特征称为决策点,叶子节点则表示最终的决策结果。
一个好的决策点可以把所有数据(例如商品)分为两部分(左子树和右子树),各部分数据所对应的类别应尽可能相同(例如购买或不购买),即两棵子树中的数据类别应尽可能“纯”(这种决策点有较高的区分度)
可以使用基尼(Gini)系数来量化数据的混乱程度。基尼系数的计算公式如下:
G = 1 − ∑ i = 1 k p k 2 G=1−∑^k_{i=1}p^2_k G=1−∑i=1kpk2
基尼系数越大说明系统不确定性越高(或越随机),基尼系数越小说明系统的不确定性越低(或越确定)
在二分类中,不难发现数据只有一个类别时, G = 1 − 1 2 = 0 G=1-1^2=0 G=1−12=0数据最纯,概率相等的时候 G = 1 − 2 ∗ ( 1 / 2 ) 2 = 0.5 G=1-2*(1/2)^2=0.5 G=1−2∗(1/2)2=0.5数据最不纯。
决策树有一些常用的构建方法,在这里我们详细讲解一下最为流行的CART树。CART树是一棵二叉树,它不仅能完成分类任务,还能完成数值预测类的回归任务。下面先介绍分类树,再介绍回归树。在构建CART树时,可以使用基尼系数来度量决策条件的合理性。
假设有 N N N个训练样本,特征一共有 m m m维,即 x = [ x 1 , ⋯ , x m ] x=[x_1,\cdots,x_m] x=[x1,⋯,xm]。这里的特征 x i x_i xi既可以时连续纸也可以是离散值。
假设我们使用划分条件 c o n d cond cond将一组样本 D a t a Data Data划分为 D a t a 1 Data_1 Data1和 D a t a 2 Data_2 Data2,其中 D a t a 1 Data_1 Data1有 M 1 M_1 M1个样本, D a t a 2 Data_2 Data2有 M 2 M_2 M2个样本。那么我们定义此次划分的基尼系数为两个子集的 G i n i Gini Gini系数加权求和:
G i n i ( c o n d ) = M 1 M 1 + M 2 G i n i ( D a t a 1 ) + M 2 M 1 + M 2 G i n i ( D a t a 2 ) Gini(cond)=\cfrac{M_1}{M_1+M_2}Gini(Data_1)+\cfrac{M_2}{M_1+M_2}Gini(Data_2) Gini(cond)=M1+M2M1Gini(Data1)+M1+M2M2Gini(Data2)
G i n i ( c o n d ) Gini(cond) Gini(cond)越小,说明 c o n d cond cond划分越合理。
因此一个简单的想法是:遍历所有维度 ( i = 1 , 2 , 3 , ⋯ , m ) (i=1,2,3,⋯,m) (i=1,2,3,⋯,m)中可能的划分条件,对每种划分方法均可计算相应的基尼系数,以最小基尼系数所对应的特征和划分条件为决策点,数据将被划分为两堆。。但是,决策树是不停生长的,仅划分一次是不够的,需要再使用同样的方法对每个子堆(Data 1、Data 2)进行划分
- 当前节点的数据集为 D。如果样本数量小于阈值、基尼系数小于阈值或没有特征,则返回决策子树,当前节点停止递归。
- 在当前节点的数据上计算各个特征的各个划分条件对划分后的数据的基尼系数。当维度过高且每维所对应的可取值比较多时(例如,价格的值为 1~10000 的整数,将有10000种划分方式;如果为浮点数,划分方式更多),可以随机选取一些特征和划分条件,不再强制要求全部遍历。
- 在计算出来的各个特征的各个特征值对数据集 D 的基尼系数中,选择基尼系数最小的特征$ x_i$ 和对应的划分条件,例如“ x i > 10 x_i>10 xi>10”或“ x i = x_i= xi=本科”。通过划分条件把数据集划分成 Data1 和 Data2 两部分,同时分别建立当前节点的左节点和右节点,左节点的数据集为 Data1,右节点的数据集为 Data2。
- 对 Data1 和 Data2 递归调用以上步骤,生成决策树。
决策树建立后,每个叶子节点里都有一堆数据。可以将这堆数据的类别比例作为叶子节点的输出。
以上介绍的是分类树,回归树除了使用方差代替基尼系数来度量数据的纯度,其他均与分类树一致,叶子节点输出的值为该节点所有样本目标值的平均值。
7.2 随机森林
然而,令人遗憾的是,在测试集(真实场景)中,决策树非常容易发生过拟合,其原因之一就是规则太“硬”。例如,以“年龄>25岁”为条件进行划分,那么26岁和24岁所对应的类别有本质区别吗?当然没有。可见,决策树把特征绝对化了。
决策树过于在意降低经验风险,其代价是结构风险较高(决策树不停生长,模型的复杂度越来越高),这也是和奥卡姆剃刀定律相悖的。通过上述分析可以发现,决策树的泛化能力不好,容易学到一些极端特例,非常容易出现过拟合。
综上所述,决策树出现过拟合的原因在于,模型不仅容易对个别特征及其取值过于敏感,还容易被个别样本影响。为了消除这些问题,我们可以选取部分特征及部分数据来构建决策树,从而在大概率上忽略极端数据。这是一个双重随机过程,具体如下:
- 第一次随机:设全体样本数为 N N N,有放回地随机抽取 M M M条数据作为训练样本。
- 第二次随机:在抽取的 M M M条样本当中,从所有特征 x = [ x 1 , x 2 , ⋯ , x m ] T x=[x_1,x_2,\cdots,x_m]^T x=[x1,x2,⋯,xm]T中随机选取特征,并且忽略其它特征。
通过双重随机选取训练样本和特征,可以构建决策树 h 1 h_1 h1。重复这个双重随机过程,构建决策树 h 2 , ⋯ , h k h_2,\cdots,h_k h2,⋯,hk。这 K K K颗决策树组成一个森林,称为随机森林 Random Forest。将这 K 棵决策树的分类结果的平均值作为最终结果,即 : y ′ = 1 K ∑ i = 1 K h i ( x ) y^{'}=\frac{1}{K}\sum_{i=1}^Kh_i(x) y′=K1∑i=1Khi(x)。(即每一颗树都会给出不同类别的概率,最终的输出是这些概率的平均)
为什么随机森林表现更好:在随机森林中,每棵决策树都是一个强分类器。强分类器在训练集上的分类效果很好,但会带来过拟合问题,而过拟合问题产生的原因就是分类器学会了数据中的随机噪声。分类器在有噪声的数据中学习,等价于给各个分类器注入了噪声。因为随机森林的预测结果是多棵决策树投票决定的,而单棵决策树由于数据噪声出现导致的分类错误会通过求平均值的计算得以消除,所以,随机森林的表现一般要优于单棵决策树。
7.3 GBDT
在二分类决策树中,将特征输入决策树,会得到分类结果 h ( x ) h(x) h(x) 决定了特征 x 将落入哪个叶子节点,并给出了对应的输出(值域为 [0,1])。叶子节点的输出只能是 [0,1],这是一个强限制。多个分类器的集成(随机森林)只能通过求平均值的方式进行,以保证最终结果的值域为 [0,1]。
梯度升级决策树(Gradient Boosting Decision Tree,GBDT)和随机森林的区别就在于:随机森林是直接获得分类概率,而GBDT是获得值域 ( − ∞ , + ∞ ) (-\infin,+\infin) (−∞,+∞)的值,然后概率为 s i g m o i d ( ∑ i = 0 K h i ( x ) ) sigmoid(\sum_{i=0}^K h_i(x)) sigmoid(∑i=0Khi(x))
这样做有什么好处呢?GBDT可以使每棵决策树的训练目标不再是最终分类结果,而是前面 k 棵决策树的结果和最终目标的差异(Gap)。这也决定了训练GBDT中的决策树需要采用串行方法:训练前 k 棵决策树,计算前 k 棵决策树的分类结果 y ′ = 1 1 + e − ∑ m = 0 k h m ( x ) y^{'}=\frac{1}{1+e^{-\sum^k_{m=0}h_m(x)}} y′=1+e−∑m=0khm(x)1和真实目标 y y y之间的误差,在训练第 k + 1 k+1 k+1颗决策树时,目标就是这个误差。
下面具体分析GBDT的学习过程:
令当前已经完成了前 k k k颗决策树的学习,那么当前的学习器为 F k ( x ) = ∑ m = 0 k h m ( x ) F_k(x)=\sum_{m=0}^kh_m(x) Fk(x)=∑m=0khm(x)也就是说当前学习器对于样本 { x i , y i } \{x_i,y_i\} { xi,yi}的预测结果为 1 1 + e − F k ( x ) \frac{1}{1+e^{-F_k(x)}} 1+e−Fk(x)1,使用 K L KL KL距离来度量 y i ′ y_i^{'} yi′和 y i y_i yi之间的差异,有: L o s s i = − y i log y i ′ − ( 1 − y i ) log ( 1 − y i ′ ) Loss_i=-y_i\log{y_i^{'}}-(1-y_i)\log{(1-y_i^{'})} Lossi=−yilogyi′−(1−yi)log(1−yi′)
在GBDT中,添加 h k + 1 ( x ) h_{k+1} (x) hk+1(x) 的目标是减小 L o s s i Loss_i Lossi,那么 h k + 1 ( x ) h_{k+1} (x) hk+1(x) 取多少才合适呢?
通过对梯度下降法的分析可以知道,为了使 L o s s i Loss_i Lossi 变小, F k + 1 ( x ) F_{k+1} (x) Fk+1(x) 应朝着 − ∂ L o s s i ∂ F k ( x i ) -\cfrac{\partial Loss_i}{\partial F_k(x_i)} −∂Fk(xi)∂Lossi的方向变化。我们这里令这个方向为 r i , k + 1 = − ∂ L o s s i ∂ F k ( x i ) = y i − y i ′ r_{i,k+1}=-\cfrac{\partial Loss_i}{\partial F_k(x_i)}=y_i-y_i^{'} ri,k+1=−∂Fk(xi)∂Lossi=yi−yi′
在训练回归树 t k + 1 ( x ) t_{k+1}(x) tk+1(x)时,使用的训练样本为 { x i , r i , k + 1 } i = 1 N \{x_i,r_{i,k+1}\}_{i=1}^N { xi,ri,k+1}i=1N
注意,这里训练的回归树是 t k + 1 ( x ) t_{k+1}(x) tk+1(x),而不是 h k + 1 ( x ) h_{k+1}(x) hk+1(x)。主要原因是: r i , k + 1 r_{i,k+1} ri,k+1是下一刻决策树的目标方向,而不是真实值,所以 t k + 1 ( x ) t_{k+1}(x) tk+1(x)只能提供正确的树结构,但是叶子节点的输出值需要修正。若 t k + 1 ( x ) t_{k+1}(x) tk+1(x)有 j = 1 , 2 , ⋯ , J k + 1 j=1,2,\cdots,J_{k+1} j=1,2,⋯,Jk+1个叶子节点,则每个叶子节点的输出可以修订为:
c k + 1 , j = ∑ x i ∈ R k + 1 , j r i , k + 1 ∑ x ∈ R k + 1 , j ( y i − r i , k + 1 ) ( 1 − y i + r i , k + 1 ) c_{k+1,j}=\cfrac{\underset{x_i\in R_{k+1,j}}{\sum}r_{i,k+1}}{\underset{x\in R_{k+1,j}}{\sum}(y_i-r_{i,k+1})(1-y_i+r_{i,k+1})} ck+1,j=x∈Rk+1,j∑(yi−ri,k+1)(1−yi+ri,k+1