上篇我们探讨了ID3算法,以及C4.5算法,也了解了C4.5算法的不足,比如不能处理回归任务,多叉树效率低等。本篇我们来探讨CART算法是如何改进C4.5算法的不足,以及决策树是如何应对过拟合问题的,最后我们对决策树算法的优缺点进行一个总结。
CART(Classification And Regression Tree)算法是我们探讨的最后一种决策树算法,也是Sklearn-Learn中决策树包使用的算法,既可以生成分类树,又可以生成回归树,也特别适合作为树模型的base model,是我们必须要掌握的一种算法。
为了优化C4.5生成多叉树时带来的效率问题,CART算法生成的是二叉树。CART算法对训练样本集的每个特征递归的进行二分判断,将特征空间划分为有限的单元。对回归树用平方误差最小化准则,对分类树用基尼指数最小化准则,进行特征选择,生成二叉树。
决策树防止过拟合的方式有两种方式,第一种是限制树的生长,比如限制树的最大深度,叶节点最小样本数等;另一种是剪枝(可以理解为正则)。
在上篇我们谈到在特征选择时,无论ID3的信息增益还是C4.5的信息增益率都存在大量的对数运算,降低模型效率。为了优化这个问题,CART算法使用基尼指数选择最优特征,基尼指数既能大致保持和熵模型同样的效果,又能避免对数运算。
基尼指数表示集合的不确定性,基尼系数越大,则样本集合的不确定性越高,这一点与熵相似。假设样本有 K K K个类,样本点属于第 k k k类的概率为 p k p_k pk,则概率分布的基尼指数的定义为:
G i n i ( p ) = ∑ k = 1 K p k ( 1 − p k ) = 1 − ∑ k = 1 K p k 2 Gini(p) = \sum_{k=1}^Kp_k(1-p_k)=1-\sum_{k=1}^Kp_k^2 Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2
对于二分类问题,如果样本点属于第1类的概率为 p p p,则概率分布的基尼指数为:
G i n i ( p ) = 2 p ( 1 − p ) Gini(p) =2p(1-p) Gini(p)=2p(1−p)
对于给定的样本集D,基尼指数为:
G i n i ( D ) = 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 Gini(D) =1-\sum_{k=1}^K(\frac{|C_k|}{|D|})^2 Gini(D)=1−k=1∑K(∣D∣∣Ck∣)2
其中, C k C_k Ck是D中属于第 k k k类的样本子集, K K K是类的个数。
如果样本集D,根据特征A将样本分割成 D 1 D_1 D1和 D 2 D_2 D2两部分,则在特征A的条件下,集合D的基尼指数为:
G i n i ( D , A ) = ∣ D 1 ∣ ∣ D ∣ G i n i ( D 1 ) + ∣ D 2 ∣ ∣ D ∣ G i n i ( D 2 ) Gini(D,A)=\frac{|D_1|}{|D|}Gini(D_1)+\frac{|D_2|}{|D|}Gini(D_2) Gini(D,A)=∣D∣∣D1∣Gini(D1)+∣D∣∣D2∣Gini(D2)
下面我们用一张图来对比在二分类问题中, G i n i Gini Gini指数, 1 2 E n t r o p y \frac{1}{2}Entropy 21Entropy,分类误差率三者的关系。横坐标表示概率 p p p,纵坐标表示 l o s s loss loss,从图中可以看出, G i n i Gini Gini和信息熵都可以近似代表分类误差率。
下面我们来简单的看下CART算法生成分类树的具体过程:
输入:训练数据集 D D D,停止条件的阈值;
输出:CART分类树;
根据训练数据集,从根节点开始,递归地对每个节点进行以下操作,构建二叉决策树:
①计算现有特征对数据集D的基尼指数。此时,对每一个特征 A A A,对其可能的每一个取值 a a a,根据样本点是否等于 a a a将数据集D分割成 D 1 D_1 D1和 D 2 D_2 D2两部分,计算 A = a A=a A=a时 G i n i ( D , A ) Gini(D,A) Gini(D,A)的值。
②在所有可能的特征 A A A以及他们所有可能的切分点 a a a中,选择基尼指数最小的特征以及其对应的切分点作为最优特征与最优的切分点。按照最优特征与最优切分点,生成两个子节点,将训练数据集依特征分配到两个子节点中去。
③对两个子节点递归地调用①②,直到满足停止条件。
④生成CART分类决策树
算法停止计算的条件有:样本集基尼系数小于指定的阈值,没有更多的特征或者节点中样本个数小于指定阈值等。
CART回归算法的原理和CART分类算法基本一样,不同之处在于,CART回归算法用均方误差最小化准则,进行特征选择,生成二叉树。
对于任意特征A,对应的任意划分点s,将数据集分割成D1和D2,求出使D1和D2各自集合的均方误差最小,同时D1和D2的均方误差之和最小所对应的特征 A ∗ ( 具 体 的 某 一 个 特 征 ) A^*(具体的某一个特征) A∗(具体的某一个特征)和特征值划分点 s ∗ ( 具 体 的 某 一 个 划 分 值 ) s^*(具体的某一个划分值) s∗(具体的某一个划分值)。表达式为:
m i n A , s [ m i n c 1 ∑ x i ϵ D 1 ( A , s ) ) ( y i − c 1 ) 2 + m i n c 2 ∑ x i ϵ D 3 ( A , s ) ) ( y i − c 2 ) 2 ] min_{A,s}[min_{c1}\sum_{x_i\epsilon D_1(A,s))} (y_i-c_1)^2+min_{c2}\sum_{x_i\epsilon D_3(A,s))} (y_i-c_2)^2] minA,s[minc1∑xiϵD1(A,s))(yi−c1)2+minc2∑xiϵD3(A,s))(yi−c2)2]
其中, c 1 c1 c1为D1数据集的样本输出均值, c 2 c2 c2为D2数据集的样本输出均值。
CART回归树的生成过程和分类树类似,下面我们具体来看下:
输入:训练数据集 D D D
输出:回归树 f ( x ) f(x) f(x)
根据训练数据集所在的输入空间,从根节点开始,递归地将每个区域划分为两个子区域并输出每个子区域的输出值,构建二叉决策树:
①遍历所有特征 A A A,对固定的特征 A A A扫描切分点 s s s,选择使得下式达到最小的切分特征 A ∗ A^* A∗与切分点 s ∗ s^* s∗。
m i n A , s [ m i n c 1 ∑ x i ϵ D 1 ( A , s ) ) ( y i − c 1 ) 2 + m i n c 2 ∑ x i ϵ D 3 ( A , s ) ) ( y i − c 2 ) 2 ] min_{A,s}[min_{c1}\sum_{x_i\epsilon D_1(A,s))} (y_i-c_1)^2+min_{c2}\sum_{x_i\epsilon D_3(A,s))} (y_i-c_2)^2] minA,s[minc1∑xiϵD1(A,s))(yi−c1)2+minc2∑xiϵD3(A,s))(yi−c2)2]
②用选定的对 ( A ∗ , s ∗ ) (A^*,s^*) (A∗,s∗)将数据集划分为 D 1 , D 2 D_1,D_2 D1,D2两部分,并输出子节点各自的均值 c m c_m cm:
D 1 ( A ∗ , s ∗ ) = { x ∣ x A ∗ ≤ s ∗ } D 2 ( A ∗ , s ∗ ) = { x ∣ x A ∗ > s ∗ } D_1(A^*,s^*)=\left \{ x|x^{A^*}\leq s^* \right \} \qquad D_2(A^*,s^*)=\left \{ x|x^{A^*}> s^* \right \} D1(A∗,s∗)={x∣xA∗≤s∗}D2(A∗,s∗)={x∣xA∗>s∗}
c ^ m = 1 N m ∑ x i ϵ R m ( A ∗ , N ) y i , x ϵ R m , m = 1 , 2 \widehat{c}_m=\frac{1}{N_m}\sum _{x_i\epsilon R_m(A^*,N)}y_i,x\epsilon R_m,m=1,2 c m=Nm1∑xiϵRm(A∗,N)yi,xϵRm,m=1,2
③对两个子节点递归地调用①②,直到满足停止条件。
④将输入空间划分为 M M M个区域 R 1 , R 2 . . . R M R_1,R_2...R_M R1,R2...RM,生成决策树:
f ( x ) = ∑ m = 1 M c ^ m I ( x ϵ R m ) f(x)=\sum _{m=1}^M\widehat{c}_mI(x\epsilon R_m) f(x)=∑m=1Mc mI(xϵRm)
其中,停止条件和分类树一样。
由于决策树几乎不对训练数据做任何的假设,如果不添加任务约束,树结构将会根据训练数据的特性自由生长,进而达到完全过拟合。因此,要对CART算法生成的树(分类树和回归树)进行剪枝(类似逻辑回归的正则化)来提高决策树的泛化能力。
CART树的剪枝方法为后剪枝,先从自由生成的决策树 T 0 T_0 T0底端开始不断剪枝,直到 T 0 T_0 T0的跟节点,形成一个子树序列 T 0 , T 1 , . . . , T n {T_0,T_1,...,T_n} T0,T1,...,Tn;然后通过交叉验证的方式在的验证数据集中对这 n n n颗树序列进行评价,选择最优的子树 T α T_\alpha Tα。
下面我们来看看剪枝的思路。首先我们计算出子树的损失函数,计算表达式为:
C α ( T ) = C ( T ) + α ∣ T ∣ C_\alpha(T)=C(T)+\alpha|T| Cα(T)=C(T)+α∣T∣,
其中 T T T为任意子树, C ( T ) C(T) C(T)为对训练数据集的预测误差(分类树是用基尼系数,回归树是均方差), ∣ T ∣ |T| ∣T∣为叶节点 个数, α \alpha α为剪枝系数,类似正则化系数。
我们先考虑两种极端情况,当 α = 0 \alpha=0 α=0时,未剪枝的决策树损失最小;当 α = + ∞ \alpha=+∞ α=+∞ 时,单跟节点的决策树损失最小。假定当前对以 r r r为根的子树剪枝,剪枝前的损失函数为:
C α ( R ) = C ( R ) + α ∣ R ∣ l e a f C_\alpha(R)=C(R)+\alpha|R|_{leaf} Cα(R)=C(R)+α∣R∣leaf
剪枝后,只保留 r r r本身,剪掉所有的叶子,损失函数为:
C α ( r ) = C ( r ) + α C_\alpha(r)=C(r)+\alpha Cα(r)=C(r)+α
当 α = 0 \alpha=0 α=0或者很小时,剪枝后的损失函数 C α ( r ) C_\alpha(r) Cα(r)大于剪枝前的损失函数 C α ( R ) C_\alpha(R) Cα(R),当 α \alpha α增大,模型复杂度对模型的惩罚变大( α ∣ R ∣ l e a f \alpha|R|_{leaf} α∣R∣leaf变大),剪枝前的损失函数会慢慢增大,当 α \alpha α增大到一定程度,总会存在一个 α \alpha α使得剪枝前和剪枝后的损失函数相等,即:
C ( R ) + α ∣ R ∣ l e a f = C ( r ) + α C(R)+\alpha|R|_{leaf} = C(r)+\alpha C(R)+α∣R∣leaf=C(r)+α
α = C ( r ) − C ( R ) < R l e a f > − 1 \alpha =\frac{C(r)-C(R)}{
那么,对于剪枝前后损失函数相等的情况,就很有必要进行剪枝。因此,我们只需选择剪枝系数 α \alpha α最小的节点,就可以进行剪枝了。
下面我们来看看CART算法剪枝过程:
输入:CART算法生成的决策树 T 0 T_0 T0;
输出:最优的决策树 T α T_\alpha Tα;
①计算所有内部节点的剪枝系数 α \alpha α;
②选择最小剪枝系数的节点,剪枝得到决策树 T k T_k Tk;
③重复以上步骤,直到决策树 T k T_k Tk只含跟节点;
④从得到的决策树序列 T 0 , T 1 , . . . , T K T_0,T_1,...,T_K T0,T1,...,TK,使用验证集选择最优的子树 T α T_\alpha Tα。
下面我们对决策树算法的优缺点进行一个总结:
优点:
缺点:
以上就是决策树算法原理总结的全部内容,下篇我们来探讨Scikit-learn中决策树库的使用。
(欢迎大家在评论区探讨交流,也欢迎大家转载,转载请注明出处)
上篇:决策树(Decision Tree)算法原理总结(一)
下篇:Scikit-learn 决策树算法库总结与简单实践