统计学习方法笔记-决策树

统计学习方法笔记-决策树

很多集成学习器,他们的基本模型都是决策树,我们经常提到的gbdt模型,它的基模型就是CRAT树.
决策树是什么东西?就是我们平常所说的if-then条件,我们把它组合成树的结构. 决策树中有两种结点,叶子结点和非叶子结点. 其中非叶节点代表的条件,叶子结点表示的实例所属的类别.

我们如何生成这个决策树呢,最主要的一点就是选择那个特征作为当前树的分割结点,这就叫做特征选择,有了特征选择就有了决策树的生成,最后我们还有进行决策树剪枝(后面会提到为什么剪枝).

之前的笔记都没有分析书中的例子,没有一个直观的解释,这次我们从这个例子出发,看一下什么是决策树.
现在我们有下面一张表的数据,想生成一个决策树模型,预测某个人是否符合贷款条件.

统计学习方法笔记-决策树

现在假如我们通过"某种方法"构造了一颗下面的决策树. 从下图可以看到特征对应的是非叶子结点,如果这个被分到这个叶节点,就预测为这个叶节点的类别. 从图中我们可以知道以下两点:

  1. 每一个叶子节点都对应一条从根节点到叶节点的规则,这表示决策树是if-then规则的集合
  2. 如果一个实例到达了某个叶节点,一定表示它满足了从根节点到该叶子节点的所有条件,而后才得到类别,这不就是先满足条件再得到概率嘛,我们一般叫做条件概率分布.
统计学习方法笔记-决策树

问题来了,为什么我们要选择是否有房子作为第一个构造特征呢?我们构造学习模型,会遵守经验风险最小化或者似然函数极大规则,选择损失函数,我们如何根据风险最小化,选择特征呢?

数据

给定训练数据集
T={(x1,y1),(x2,y2),...,(xN,yN)}T=\{(x_1,y_1),(x_2,y_2),...,(x_N,y_N)\}
其中,xi=(xi(1),xi(2),...,xi(n))Tx_i=(x_i^{(1)},x_i^{(2)},...,x_i^{(n)})^T特征向量,n是特征的个数,yi{1,2,...,K}y_i \in \{1,2,...,K\}表示类别. N是样本个数. 基于这个数据生成决策树模型.

决策树

常见的决策树模型有以下三种(决策树既可以做分类也可以做回归):

  1. ID3
  2. C4.5
  3. CART

先给出两个定义,信息熵和条件熵:

信息熵表示随机变量不确定性的度量,设随机标量X是一个离散随机变量,其概率分布为:
P(X=xi)=pi,i=1,2,...,nP(X=x_i)=p_i, i=1,2,...,n
则随机变量X的熵定义为:
H(X)=i=1npilogpiH(X)=-\sum_{i=1}^{n}p_ilog{p_i}
熵越大,随机变量的不确定性就越大,当pi=1np_i=\frac{1}{n}$时,
随机变量的熵最大等于logn,故0H(P)logn0 \leq H(P) \leq logn.

条件熵就是在给定X的条件的情况下,随机标量Y的条件,记作H(YX)H(Y|X),可以结合贝叶斯公式进行理解,定义如下
H(YX)=i=1npiH(YX=xi)H(Y|X)=\sum_{i=1}^{n}p_iH(Y|X=x_i)
这里pi=P(X=xi),i=1,2,...,np_i=P(X=x_i),i=1,2,...,n.
一般在基于数据的估计中,我们使用的基于极大似然估计出来的经验熵和经验条件熵.

model feature select 树的类型 计算公式
ID3 {分类:信息增益} 多叉树 g(D,A)=H(D)H(DA)g(D,A)=H(D)-H(D\|A)
C4.5 {分类:信息增益比} 多叉树 gR(D,A)=g(D,A)HA(D)g_R(D,A)=\frac{g(D,A)}{H_A(D)}
CART {回归:平方误差;分类:基尼指数} 二叉树 Gini(p)=k=1Kpk(1pk)=1k=1Kpk2Gini(p)=\sum_{k=1}^{K}p_k(1-p_k)=1-\sum_{k=1}^{K}p_k^2

其中, HA(D)=H(DA)H_A(D)=H(D|A).

从表格中,我们总结(ID3,C4.5)决策树算法伪代码:

  1. 输入:数据集D,特征集合A,阈值e
  2. 输出:决策树T
  3. 如果D中所有实例输出同一类CkC_k, 则T作为单节点树,并将类CkC_k作为该节点的类标记,返回T;
  4. A=A=\varnothing,则T为单节点树,将D中实例数最多的类CkC_k作为该节点的类标记,返回T;
  5. 否则,根据信息增益(ID3)或者信息增益比(C4.5)计算特征A对D的值,选择当前最优的特征AgA_g;
  6. 如果AgA_g的信息增益小于阈值e,则置T为单节点数,并将D中实例最多的类CkC_k作为当前的类标记,返回T;
  7. 否则,根据AgA_g中的每一个不同的aia_i,根据Ag=aiA_g=a_i将D分成若干个非空子集,对于第i个子节点,以DiD_i为数据集,以AAgA-{A_g}为特征集,递归(重复3-6)构造决策树TiT_i,返回TiT_i.
  8. 对决策树模型T进行剪枝.

从上述算法中,我们有三个问题,需要再次提出,并进行解释:

  1. 为什么使用信息增益,越大越能得到好的模型?

上面提到过,信息熵表示数据的混乱的程度,信息增益是信息熵和条件信息熵的差值,表示的熵减少的程度,信息增益越大,代表根据我们的决策树规则得到的数据越趋向于规整,这就是我们划分类别的目的.

  1. 为什么从信息增益变到信息增益比,目的何在?

信息增益根据特征之后的条件信息熵,这样的话偏向于特征取值较多的特征的问题,因此使用信息增益比对这个问题进行校正.

  1. 为什么要进行剪枝?

在构造决策树的过程中,我们的两个停止条件是,子集只有一个类别和没有可以选择的特征,这是我们全部利用了数据中的所有可以使用的信息,但是我们知道数据是可能有误差了,而且数据不足,我们需要得到更鲁棒的模型,剪枝的意义就是是的深度减小,这样的就相当于减少规则的情况下,决策树的性能反而不差,使其更加鲁棒.

剪枝

再说为什么剪枝,我们构造决策树的时候,是完全的在训练数据上得到最优的模型. 这就是问题,这就什么,这就过拟合,训练误差很小,但是验证集上就不怎么好用. 损失=经验风险最小化+正则项=结构风险最小化. 构造决策树的时候只考虑了经验风险最小化,剪枝的时候我们考虑结构风险最小化,正则项就是树的叶子节点个数. 重新定义损失函数,树的叶子节点个数|T|,t是树T的叶节点,该叶节点有NtN_t个样本,其中k类的样本点有NtkN_{tk}个,k=1,2,…,K, Ht(T)H_t(T)是叶子节点t经验熵,α0\alpha \leq 0是参数,平衡经验损失和正则项,得到计算公式如下:
Cα(T)=t=1TNtHt(T)+αTC_{\alpha}(T)=\sum_{t=1}^{|T|}N_tH_t(T)+\alpha|T|
其中,经验熵为:
Ht(T)=kNtkHtlogNtkHtH_t(T)=-\sum_{k}\frac{N_{tk}}{H_t}log\frac{N_{tk}}{H_t}
这是有:
Cα=C(T)+αTC_{\alpha}=C(T)+\alpha|T|
决策树剪枝优化过程考虑了在训练数据上的经验风险最小化和减小模型复杂度两个方向. 因为加了正则项,所有我们基于贪心的思想进行剪枝,因为当剪掉一个树节点,虽然经验风险增加了,但是模型复杂度降低了,我们基于两个方面的平衡进行剪枝,如果剪掉之后,总的风险变小,就进行剪枝.
算法:
输入: 算法产生的整个决策树,参数α\alpha
修剪之后的树TαT_{\alpha}

  1. 计算每个节点的经验熵
  2. 递归从树的叶节点向上回溯,假设将某个叶节点回缩到其父节点前后的整体树对应的TBT_BTAT_A,对应的损失分别是Cα(TB)C_{\alpha}(T_B)Cα(TA)C_{\alpha}(T_A),如果:
    Cα(TA)Cα(TB)C_{\alpha}(T_A) \leq C_{\alpha}(T_B)
    表示,剪掉之后,损失减小,就进行剪枝.
  3. 重复2,直到不能继续为止,得到损失函数最小的子树TαT_{\alpha}. 注: 动态规划加速,是个好方法.

CART

分类与回归树(classification and regression tree, CART)与上述决策树的不同,

  1. 既可以做分类又可以做回归.
  2. 是二叉树,内部节点特征取值,只有yes和no两个选项
    同样地,先进行决策树构造,在基于验证集上进行CART决策树的剪枝,既然是回归和分类树,我们就分别介绍回归和分类两种情况.
  • 分类: gini指数
  • 回归: 平方误差
    定义数据格式:
    D=(x1,y1),(x2,y2),...,(xN,yN)D={(x_1,y_1),(x_2,y_2),...,(x_N,y_N)}
    其中,xix_i是向量,当回归问题时,yiy_i是连续变量; 分类问题时,yiy_i是离散变量.

回归树(Regerssion Tree)

算法:
在训练数据上,根据某一个特征将每个区域划分为两个子区域并决定每个子区域的输出值,递归构建二叉树.

  1. 选择最优切分变量j和切分点s,求解
    minj,s[minc1xiR1(j,s)(yic1)2+minc2xiR2(j,s)(yic2)2]min_{j,s}[min_{c_1}\sum_{x_i \in R_1(j,s)}(y_i-c_1)^2 + min_{c_2}\sum_{x_i \in R_2(j,s)}(y_i-c_2)^2]
    遍历变量j,对固定的切分变量j扫描所有的s,找到使得上式最小的对(j,s).
  2. 使用选定的(j,s)划分区域并决定相应的输出值:
    R1(j,s)={xx(j)s},R2(j,s)={xx(j)>s},R_1(j,s)=\{x|x^{(j)} \leq s \}, R_2(j,s)=\{x|x^{(j)} > s \},
    cm=1NmxiRm(j,s)yi,xRm,m=1,2c_m=\frac{1}{N_m}\sum_{x_i \in R_m(j,s)}y_i, x \in R_m, m=1,2
  3. 继续对两个子区域调用1和2,知道满足条件
  4. 将输入空间划分为M个区域R1,R2,...,RmR_1,R_2,...,R_m,生成决策树:
    f(x)=m=1McmI(xRm)f(x)=\sum_{m=1}^{M}c_mI(x \in R_m)

分类树(classification tree)

基尼指数计算公式如下:
Gini(p)=k=1Kpk(1pk)=1k=1Kpk2Gini(p)=\sum_{k=1}^{K}p_k(1-p_k)=1-\sum_{k=1}^{K}p_k^2
基于数据D,得到:
Gini(D)=1k=1Kpk2Gini(D)=1-\sum_{k=1}^{K}p_k^2
其中,CkC_k是D中所属第k类的样本子集,K是类的个数.
如果样本集合D根据特征A是否取某一可能取值a被被划分成D1D_1D2D_2两个部分.
D1={(x,y)DA(x)=a},D2=DD1D_1=\{(x,y) \in D | A(x)=a \}, D-2= D-D_1
在特征A的条件下,集合D的基尼指数定义为:
Gini(D,A)=D1DGini(D1)+D2DGini(D2)Gini(D,A)=\frac{|D_1|}{D}Gini(D_1)+\frac{|D_2|}{D}Gini(D_2)
基尼指数和熵一样,同样表示集合D的不确定性,基尼指数(Gini(D,A))表示根据调教A=a后的集合D的不确定性,基尼指数越大,表示数据D的不确定性越大.

算法:
输入:训练数据D,停止计算的条件
输出:CART决策树

  1. 计算所有特征A的每一个值a对应的条件基尼指数的值,选择最优的划分得到D1D_1D2D_2.
  2. 递归对两个数据集D1D_1D2D_2继续调用1,知道满足条件.
  3. 生成CART树的分类树.
  4. 预测的时候,根据决策树,x落到的叶子节点对应的类别表示这个预测x的类别.

CART剪枝

从上面两个算法的不同可以看出,只是在label的设置和决策节点选择的方式不同,整个架构依然是决策树的常用的架构. 而且上面的树的构建过程,都是基于训练数据的经验风险最小化,没有使用带有正则项的结构风险最小化,这样的模型容易发生过拟合,为了不让模型过拟合,我们需要进行模型的剪枝.

CART树的剪枝有很多难点和有意思的地方让我们开慢慢解开这层面纱
CART剪枝算法有两步组成:

  1. 从生成算法产生的决策树T0T_0底端开始不断剪枝,直到T0T_0的根节点,形成一个子树序列{T0,T1,...,Tn}\{T_0,T_1,...,T_n\}.
  2. 通过交叉验证的方法在独立的验证数据集上堆子序列进行测试,得到最优子树

损失函数:
Cα(T)=C(T)+αTC_{\alpha}(T)=C(T)+\alpha|T|
其中,T为任意子树,C(T)C(T)是在训练数据上的预测误差,|T|是树的叶子节点的个数,α0\alpha \geq 0是参数,Cα(T)C_{\alpha}(T)是参数α\alpha是的子树T的整体的损失,参数α\alpha是平衡训练数据拟合程度和模型复杂度的权重.
对于固定的α\alpha,一定存在使损失函数Cα(T)C_{\alpha}(T)最小的子树,将其记作TαT_{\alpha}. 我们可以理解为每一个α\alpha都对应一个最有子树和最小损失.

而且已经得到证明,可以用递归的方法对树进行剪枝. 将α\alpha从小增大,0=α0<α1<...<αn<+0=\alpha_0<\alpha_1<...<\alpha_n<+\infty,产生一系列的区间[αi,αi+1),i=0,1,...,n[\alpha_i,\alpha_{i+1}),i=0,1,...,n;剪枝得到的子树序列对应着区间α[αi,αi+1),i=0,1,...,n\alpha \in [\alpha_i,\alpha_{i+1}),i=0,1,...,n的最有子树序列{T0,T1,...,Tn}\{T_0,T_1,...,T_n\}.

我们给出算法:
输入: CART算法生成的决策树T_0.
输出: 最优的决策树T_{\alpha}

  1. 设k=0, T=T0T_0.
  2. α=+\alpha=+\infty.
  3. 自下而上地对各个内部节点t计算C(Tt),TtC(T_t),|T_t|以及
    g(t)=C(t)C(Tt)Tt1g(t)=\frac{C(t)-C(T_t)}{|T_t|-1}
    α=min(α,g(t))\alpha=min(\alpha,g(t))
    这里,TtT_t表示以t为根节点的子树,C(Tt)C(T_t)是对训练数据的预测误差,Tt|T_t|TtT_t的叶子节点个数.
  4. 自上而下地访问内部节点t,如果有g(t)=αg(t)=\alpha,进行剪枝,并堆叶节点t以多数表决方法决定其类(分类,回归使用平均值),得到树T.
  5. k=k+1,α=α,Tk=Tk=k+1,\alpha=\alpha,T_k=T.
  6. 如果T不是由根节点单独构成的树,则回到步骤4.
  7. 采用交叉验证法在子树序列{T0,T1,...,Tn}\{T_0,T_1,...,T_n\}中选取最优子树TαT_{\alpha}.

接下面,我们不去看算法,来看书中给的一段文字的截图,这里截图是因为我要画图,进行比较解释,图中*理论(哈哈):

统计学习方法笔记-决策树

看懂这个图之后,再看算法一气呵成,因为我们假设每一次得到的树都有可能是最优的,所以不能直接去最后一个树,要使用交叉验证选择最有的决策树结构.

总结

决策树用途相当广泛,而且有很多变形,看着简单其实不易,需要看看探索每一个知识点. 目前机器学习,人工智能如此火热,需要进行理论实践学习等多方面的结合方能立于不败之地.

注:生活如此,问题不大. 喵~