1 算法简介
决策树模型是树形结构,既可以用于分类,也可以用于回归。一颗决策树由结点和有向边组成,结点分为内部结点(包括根结点,表示特征)和叶结点(表示类),有向边的权值表示特征的一个取值。
为了方便描述,设训练数据集D = {(x1,y1),(x2,y2),…,(xN,yN)},其中N为样本个数,|D|表示数据集D的样本容量,|D|=N。
xi = {xi(1),xi(2),…,xi(n)}为输入实例(内部结点),n为特征个数,为了简洁,我们用{A1,A2,…,An,} 来代替{xi(1),xi(2),…,xi(n)},特征Ai有m个不同的取值{a1,a2,…,am}。
根据特征Ai的不同取值将D划分为m个子集D1,D2,…,Dm。|Di|为Di的样本个数,
∑
i
=
1
m
∣
D
i
∣
=
∣
D
∣
\sum_{i=1}^{m}|D_i|=|D|
∑i=1m∣Di∣=∣D∣。
设数据集D有K个类Ck,|Ck|为属于类Ck的样本个数,
∑
k
=
1
K
∣
C
k
∣
=
∣
D
∣
\sum_{k=1}^{K}|C_k|=|D|
∑k=1K∣Ck∣=∣D∣。|Dik|为子集Di中属于类Ck的样本个数。
yi 为类标记(叶结点),我们要做的就是用训练集T构建一个决策树模型,使它能够对实例xi进行正确的分类。
2 特征选择
决策树学习算法递归地选择最优特征,并根据该特征对训练数据进行分割,使得对各个子数据集有一个最好的分类的过程。
特征选择在于选取对训练数据具有分类能力的特征,一个没有分类能力的特征是可以扔掉的。
那么什么是没有分类能力的特征呢?用一个特征进行分类的结果和随机分类的结果没有很大区别时,就称该特征没有分类能力。
特征选择的准则是信息增益或信息增益比。为了更好地解释这个准则,我们需要一步步介绍这几个概念。
- 熵
熵H(Y)是表示随机变量不确定性的度量。设离散随机变量Y的概率分布为:
p i = P ( Y = y i ) , i = 1 , 2 , . . . , n p_i=P(Y=y_i),i=1,2,...,n pi=P(Y=yi),i=1,2,...,n
n为Y的所有可能取值个数,则离散随机变量Y的熵为:
H ( Y ) = − ∑ i = 1 n p i l o g p i , 0 ≤ H ( p ) ≤ l o g n H(Y)=-\sum_{i=1}^{n}p_ilogp_i,0 \le H(p) \le logn H(Y)=−i=1∑npilogpi,0≤H(p)≤logn
在这里定义,若pi=0,则0log0=0,通常这里的对数以2或e为底。 - 条件熵
条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性。
它定义为X给定条件下Y的条件概率分布的熵对X的数学期望:
H ( Y ∣ X ) = ∑ i = 1 n p i H ( Y ∣ X = x i ) H(Y|X)=\sum_{i=1}^{n}p_iH(Y|X=x_i) H(Y∣X)=i=1∑npiH(Y∣X=xi)
熵和条件熵从某方面来说反应了信息的混乱程度,熵和条件熵越大,说明做一个决定的不确定性就越大。
例如,当P(出去玩)=P(不去玩)= 1 2 \frac{1}{2} 21时,决定要不要出去玩就会非常困难,当P(出去玩|下雨)= 1 10 \frac{1}{10} 101,P(不去玩|下雨)= 9 10 \frac{9}{10} 109时,决定要不要出去玩就会由于增加了“是否下雨”这个特征变得非常容易,因为下雨时很大概率会选择不出去玩。 - 经验熵和经验条件熵
经验熵和经验条件熵是由极大似然估计等数据估计法得到的熵和条件熵。
计算数据集D的经验熵:
H ( D ) = − ∑ k ∣ C k ∣ ∣ D ∣ l o g 2 ∣ C k ∣ ∣ D ∣ H(D)=-\sum_{k}\frac{|C_k|}{|D|}log_2{\frac{|C_k|}{|D|}} H(D)=−k∑∣D∣∣Ck∣log2∣D∣∣Ck∣
计算特征A对数据集D的经验条件熵:
H ( D ∣ A ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ H ( D i ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ [ − ∑ k ∣ D i k ∣ ∣ D i ∣ l o g 2 ∣ D i k ∣ ∣ D i ∣ ] \begin{aligned} H(D|A)&=\sum_{i=1}^{n}\frac{|D_i|}{|D|}H(D_i)\\ &=\sum_{i=1}^{n}\frac{|D_i|}{|D|}{}[-\sum_{k}\frac{|D_{ik}|}{|D_i|}log_2{\frac{|D_{ik}|}{|D_i|}}] \end{aligned} H(D∣A)=i=1∑n∣D∣∣Di∣H(Di)=i=1∑n∣D∣∣Di∣[−k∑∣Di∣∣Dik∣log2∣Di∣∣Dik∣] - 信息增益
信息增益 g(Y,X) 表示得知X的信息而使得Y的信息的不确定性减少的程度,定义为熵H(Y)与条件熵H(Y|X)之差:
g ( Y , X ) = H ( Y ) − H ( Y ∣ X ) g(Y,X)=H(Y)-H(Y|X) g(Y,X)=H(Y)−H(Y∣X)
计算特征A对数据集D的信息增益:
g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A)=H(D)-H(D|A) g(D,A)=H(D)−H(D∣A)
根据信息增益准则的特征选择方法是:对训练数据集D,计算其每个特征的信息增益,并比较它们的大小,选择信息增益最大的特征。
以信息增益准则划分训练数据集的特征,会“偏心”取值较多的特征。为了解决上诉问题,提出了信息增益比。 - 信息增益比
信息增益比gR(Y,X)是信息增益 g(Y,X)与关于X的值的熵HX(Y)之比:
g R ( Y , X ) = g ( Y , X ) H X ( Y ) g_R(Y,X) =\frac{g(Y,X)}{H_X(Y)} gR(Y,X)=HX(Y)g(Y,X)
计算特征A对数据集D的信息增益比:
g R ( D , A ) = g ( D , A ) H A ( D ) = H ( D ) − H ( D ∣ A ) − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ l o g 2 ∣ D i ∣ ∣ D ∣ \begin{aligned} g_R(D,A)&=\frac{g(D,A)}{H_A(D)}\\ &=\frac{H(D)-H(D|A)}{-\sum_{i=1}^{n}\frac{|D_{i}|}{|D|}log_2{\frac{|D_{i}|}{|D|}}} \end{aligned} gR(D,A)=HA(D)g(D,A)=−∑i=1n∣D∣∣Di∣log2∣D∣∣Di∣H(D)−H(D∣A)
3 生成决策树
生成决策树的经典算法主要是ID3和C4.5。
ID3
ID3算法用信息增益准则递归地选择最优特征构建决策树,用极大似然估计法计算信息增益,直到所有特征的信息增益均很小或无特征可选为止。但该算法只有树的生成,没有剪枝操作,容易产生过拟合。
ID3算法的具体步骤如下:
- 输入训练数据集D、特征集合A、阈值 ε \varepsilon ε。
- 若D中所有样本属于同一类Ck,则输出单结点决策树T,该结点的类标记为Ck。
- 若特征集合A是空集,也就是没有任何特征,则输出单结点决策树T,该结点的类标记为D中实例最多的类Ck。
- 否则,计算A中各特征对训练集D的信息增益,选择信息增益最大的特征Ag。
1) 若最优特征Ag的信息增益小于阈值 ε \varepsilon ε,说明剩下的结点都是没有分类能力的,没有必要再继续细分下去,那么输出单结点决策树T,该结点的类标记为D中实例最多的类Ck。
2) 否则,对特征Ag的每一个可能取值ai,将训练集D分割为若干个非空子集Di。
3) 为每一个子集Di生成一个分支,分支的权值就是ai。
4) 将子集Di和剩下的特征集A-{Ag}输入,重复步骤2-4。(递归的思想) - 输出一颗决策树T。
C4.5
C4.5是ID3的改进,唯一的区别是使用信息增益比准则来选择最优特征。
4 修剪决策树
当决策树生成算法过多地考虑如何精确分类训练数据集时,就会构建出过于茂盛的决策树,导致泛化能力不是很高,即出现过拟合。解决过拟合的办法就是简化已生成的树,也就是裁掉一些子树,进行剪枝。
剪枝算法的主要思想为极小化决策树整体的损失函数。
下面来学习一下如何计算这个损失函数。
- 设一颗已经生成的决策树T,|T|是树T中表示分类的叶结点个数,某叶结点t有Nt个样本点,Ntk表示这Nt个样本点中属于k类的样本点个数,Ht(T)表示叶结点t的经验熵, α \alpha α是用在正则项中的参数, α ≥ 0 \alpha\ge0 α≥0。
- 那么模型对训练数据的预测误差(模型与训练数据的拟合程度)为:
C ( T ) = ∑ t = 1 ∣ T ∣ N t H t ( T ) = ∑ t = 1 ∣ T ∣ N t { − ∑ k = 1 K N t k N t l o g N t k N t } = − ∑ t = 1 ∣ T ∣ ∑ k = 1 K N t k l o g N t k N t \begin{aligned} C(T)&=\sum_{t=1}^{|T|}N_tH_t(T)\\ &=\sum_{t=1}^{|T|}N_t\{-\sum_{k=1}^{K}\frac{N_{tk}}{N_{t}}log\frac{N_{tk}}{N_{t}}\} \\ &=-\sum_{t=1}^{|T|}\sum_{k=1}^{K}N_{tk}log\frac{N_{tk}}{N_{t}} \end{aligned} C(T)=t=1∑∣T∣NtHt(T)=t=1∑∣T∣Nt{−k=1∑KNtNtklogNtNtk}=−t=1∑∣T∣k=1∑KNtklogNtNtk - 加上正则化项
α
∣
T
∣
\alpha|T|
α∣T∣的损失函数为:
C α ( T ) = C ( T ) + α ∣ T ∣ C_\alpha(T)=C(T)+\alpha|T| Cα(T)=C(T)+α∣T∣
左边这一项是模型与训练数据的拟合程度,越小越好;右边这一项是模型的复杂度,也应该越小越好。只有拟合的好且简单的模型,整体损失函数才会很小。
参数 α \alpha α控制两者影响损失函数的程度大小, α \alpha α越大,越“偏心”简单的模型, α \alpha α越小,越“偏心”与训练数据拟合精确的模型, α \alpha α=0意味着不考虑模型的复杂度,相当于C(T)。
学会计算决策树的损失函数后,树的剪枝算法就非常好理解了,具体步骤如下:
- 输入由生成算法产生的整个决策树T,参数 α \alpha α。
- 计算每个结点的经验熵。
- 递归地从叶结点向上回缩,若回缩后的损失函数比回缩前的损失函数更小,则进行剪枝,将更加细分的子树剪掉,子树的根结点变为新的叶结点。
- 递归执行步骤3,直到不能继续为止,输出损失函数最小的决策树 T α T_\alpha Tα。
注:步骤3中每次只从两个树中选择更优的树,此处可以借助动态规划思想实现。
5 CART算法
CART算法的全称是分类与回归树模型,顾名思义,既可以用于分类,也可以用于回归,最后生成的决策树是二叉树,左分支取值为“是”,右分支取值为“否”。
CART算法主要由生成和剪枝两部分组成:
CART回归树的生成
基于训练数据集递归地构建尽可能大的二叉决策树。
准则:平方误差最小化
最终生成的回归树相当于把输入空间划分成了M个区域R1,R2,…,RM,每个区域都根据某个准则选则一个输出(比如投票或者求平均值),就像下图这样,把输入空间划分成了4个区域,每个区域对应着一个输出(+1或-1):
最后预测的时候,输入落在哪个区域,就输出哪个区域对应的输出结果。
生成回归树的步骤如下:
- 输入训练数据集D={(x1,y1),(x2,y2),…,(xN,yN)},这里的变量X和Y都是连续的。
- 划分输入空间。
首先我们要把一整个输入空间一分为二,再递归地将这两个区域二分为四,四分为八…直到满足停止条件,输入空间就划分好了。这里可能会有人问,为什么不能一分为三?或一分为更多呢?因为前面我们说过,CART树是一个二叉树,它的每个特征在这里,都只有两种取值。
接下来最重要的问题就是,一个输入有那么多特征,先选择哪个特征来划分空间?按照什么原则来找该特征能把区域一分为二的切分点?
首先对于一个特征来说,存在很多切分点可以将区域划分为两部分。那么我们遍历所有的切分点后,一定有一个最优切分点,可以使落在两个区域内的样本的平方误差之和最小。(这里的平方误差,就是区域内每个样本的真实取值与均值之差的平方,这里的均值就是所有落在第一个区域上的训练样本的输出yi的均值和所有落在第二个区域上的均值。)
然后对于每一个特征,都能找到它们的最优切分点,并得到它们的最小平方误差之和。那么在所有特征中,平方误差之和最小的那个特征,就是我们要找的最优切分特征。
具体计算如下:
首先选择第j个特征x(j)和x(j)的取值s,作为切分特征和切分点,将输入空间划分为R1,R2两个区域:
R 1 = { x ∣ x ( j ) ≤ s } R 2 = { x ∣ x ( j ) > s } R_1=\{x|x^{(j)}\le s\}\\ R_2=\{x|x^{(j)}> s\} R1={x∣x(j)≤s}R2={x∣x(j)>s}
落在两个区域的训练样本的输出yi的均值 c 1 ^ 、 c 2 ^ \hat{c_1}、\hat{c_2} c1^、c2^为:
c 1 ^ = a v e ( y i ∣ x i ∈ R 1 ) c 2 ^ = a v e ( y i ∣ x i ∈ R 2 ) \hat{c_1}=ave(y_i|x_i\in R_1)\\ \hat{c_2}=ave(y_i|x_i\in R_2) c1^=ave(yi∣xi∈R1)c2^=ave(yi∣xi∈R2)
遍历所有特征x(j)的所有切分点,最优特征x(j)和它的最优切分点s满足:
m i n j , s [ m i n ∑ x i ∈ R 1 ( y i − c 1 ^ ) 2 + m i n ∑ x i ∈ R 2 ( y i − c 2 ^ ) 2 ] \underset {j,s}{min}[min\sum_{x_i\in R_1}(y_i-\hat{c_1})^2+min\sum_{x_i\in R_2}(y_i-\hat{c_2})^2] j,smin[minxi∈R1∑(yi−c1^)2+minxi∈R2∑(yi−c2^)2] - 决定两个区域的输出值为均值 c 1 ^ 、 c 2 ^ \hat{c_1}、\hat{c_2} c1^、c2^。
- 递归地对两个子区域重复步骤2和3,直到满足停止条件为止。按照这样的方法得到的树也叫最小二乘回归树。
- 生成最终的回归树模型:
f ( x ) = ∑ m = 1 M c m ^ I ( x ∈ R m ) f(x)=\sum_{m=1}^{M}\hat{c_m}I(x\in R_m) f(x)=m=1∑Mcm^I(x∈Rm)
M为划分完后区域的个数,当输入一个x时,这个x一定落在输入空间的某一个区域上。模型遍历所有的区域,当遍历到的区域不是x落到的区域时,指示函数会置0,当遍历到的区域是x落到的区域时,指示函数会置1,并与该区域的输出 c m ^ \hat{c_m} cm^相乘。累加后输出的结果就是x的分类结果。
CART分类树的生成
准则:基尼指数最小化
与回归树不同的是,分类树将基尼指数最小的特征和特征下的切分点作为最优特征和最优切分点。
基尼指数值越大,集合的不确定性越大,也就越混乱,这一点与之前学的熵相似。
生成分类树的步骤如下:
- 输入训练数据集D={(x1,y1),(x2,y2),…,(xN,yN)},这里的变量X和Y都是离散的。
- 遍历特征集合A和每个特征的所有可能取值,选择最优特征和最优切分点,具体地如下:
首先引入基尼指数的概念,假设有K个类,样本点属于第k类的概率为pk,不属于第k类的概率为1-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}^{K}p_k(1-p_k)=1-\sum_{k=1}^{K}p_k^2 Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2
当使用极大似然估计法时, p k = 在集合 D 中属于第 k 类的样本个数 集合 D 的样本个数 = ∣ C k ∣ ∣ D ∣ p_k=\frac{在集合D中属于第k类的样本个数}{集合D的样本个数}=\frac{|C_k|}{|D|} pk=集合D的样本个数在集合D中属于第k类的样本个数=∣D∣∣Ck∣。
那么集合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
根据是否等于特征x(j)的某个取值a,可以将集合D分割成D1D2两个子集合,则在特征x(j)=a的条件下,集合D的基尼指数为:
G i n i ( D , x ( j ) = a ) = ∣ D 1 ∣ ∣ D ∣ G i n i ( D 1 ) + ∣ D 2 ∣ ∣ D ∣ G i n i ( D 2 ) = ∣ D 1 ∣ ∣ D ∣ [ 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D 1 ∣ ) 2 ] + ∣ D 2 ∣ ∣ D ∣ [ 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D 2 ∣ ) 2 ] \begin{aligned} Gini(D,x^{(j)}=a)&=\frac{|D_1|}{|D|}Gini(D_1)+\frac{|D_2|}{|D|}Gini(D_2)\\ &=\frac{|D_1|}{|D|} [1-\sum_{k=1}^{K} {(\frac{|C_k|}{|D_1|})}^2]+\frac{|D_2|}{|D|} [1-\sum_{k=1}^{K} {(\frac{|C_k|}{|D_2|})}^2] \end{aligned} Gini(D,x(j)=a)=∣D∣∣D1∣Gini(D1)+∣D∣∣D2∣Gini(D2)=∣D∣∣D1∣[1−k=1∑K(∣D1∣∣Ck∣)2]+∣D∣∣D2∣[1−k=1∑K(∣D2∣∣Ck∣)2]
遍历特征集合A和每个特征的所有可能取值,计算出所有的基尼指数,选择最优特征Ag和最优切分点a。 - 从根结点开始,对特征集合A-Ag(上一步用过的最优特征要去掉)和子集合,递归地重复步骤2,直到满足停止条件为止。
- 生成CART决策树分类模型。
CART剪枝
基于验证数据集(注意在生成过程中用的是训练数据集)对前面步骤生成的树进行剪枝,得到最优决策树。
关于这部分内容,有一篇知乎写的很好