决策树
上一篇博客从数学原理和代码角度解释了逻辑回归,接下来我们将介绍决策树。
专栏链接
数学原理
一颗完整的决策树包含以下三个部分:
- 根节点:就是树最顶端的节点,即初始特征
- 叶子节点:树最底部的节点,也就是决策结果
- 内部节点:除了叶节点,都是内部节点
决策树采用的是自顶向下的递归方法,其基本思想是以信息熵为度量构造一棵熵值下降最快的树,到叶子节点的熵值为0,此时每个叶子节点的实例都属于同一类。
信息论知识
信息熵概念
离散型随机变量X的取值为X1、X2、...、Xn,发生概率分别为P1、P2、...、Pn,则信息熵为:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H ( X ) = − ∑ i = 1 n p i l o g ( p i ) H(X)=-\sum_{i=1}^np_ilog(p_i) </math>H(X)=−i=1∑npilog(pi)
信息熵用于描述信息的不确定度,概率越大,可能性越大,信息量越小,不确定度越小,熵越小。
条件熵
设随机变量(X, Y)具有联合概率分布:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> P ( X = x i , Y = y i ) = p i j P(X=x_i,Y=y_i)=p_{ij} </math>P(X=xi,Y=yi)=pij
条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性。
(X, Y)发生所包含的熵,减去X单独发生的熵,就是在X发生的前提下,Y发生带来的熵
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H ( Y ∣ X ) = H ( X , Y ) − H ( X ) H(Y|X)=H(X,Y)-H(X) </math>H(Y∣X)=H(X,Y)−H(X)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H ( X , Y ) − H ( X ) = − ∑ x , y p ( x , y ) l o g p ( x , y ) + ∑ x p ( x ) = − ∑ x , y p ( x , y ) l o g p ( x , y ) + ∑ x ( ∑ y p ( x , y ) ) l o g p ( x ) = − ∑ x , y p ( x , y ) l o g p ( x , y ) + ∑ x , y p ( x , y ) l o g p ( x ) = − ∑ x , y p ( x , y ) l o g p ( y ∣ x ) H(X,Y)-H(X)=-\sum_{x,y}p(x,y)logp(x,y)+\sum_xp(x) =-\sum_{x,y}p(x,y)logp(x,y)+\sum_x(\sum_yp(x,y))logp(x) =-\sum_{x,y}p(x,y)logp(x,y)+\sum_{x,y}p(x,y)logp(x) =-\sum_{x,y}p(x,y)logp(y|x) </math>H(X,Y)−H(X)=−x,y∑p(x,y)logp(x,y)+x∑p(x)=−x,y∑p(x,y)logp(x,y)+x∑(y∑p(x,y))logp(x)=−x,y∑p(x,y)logp(x,y)+x,y∑p(x,y)logp(x)=−x,y∑p(x,y)logp(y∣x)
相对熵
ID3算法
核心是在决策树各个节点上应用信息增益准则选择特征,递归地构建决策树。
**具体方法是:**从根结点开始,对节点计算所有可能特征的信息增益,选择信息增益最大的特征作为节点的特征,由该特征的不同取值建立子节点,再对子节点递归的调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止。
ID3相当于用极大似然法 进行概率模型的选择。使用二分法则易于对树构建过程中进行调整以处理连续性特征 。具体的处理方法是:如果特征值大于给定值就走左子树,否则走右子树。
**信息增益:**给定一个样本集D,划分前样本集合D的熵是一定的,用H0表示,使用某个特征A划分数据集D,计算划分后的数据子集的熵,用H'表示。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 信息增益 = H 0 − H ′ 信息增益=H_0-H' </math>信息增益=H0−H′
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H 0 = − 5 14 l o g 5 14 − 9 14 l o g 9 14 = 0.9403 H_0=-\frac{5}{14}log\frac{5}{14}-\frac{9}{14}log\frac{9}{14}=0.9403 </math>H0=−145log145−149log149=0.9403
选天气特征:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H 1 = − 2 5 l o g 2 5 − 3 5 l o g 3 5 = 0.9710 H_1=-\frac{2}{5}log\frac{2}{5}-\frac{3}{5}log\frac{3}{5}=0.9710 </math>H1=−52log52−53log53=0.9710
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H 2 = − l o g 1 = 0 H_2=-log1=0 </math>H2=−log1=0
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H 3 = − 2 5 l o g 2 5 − 3 5 l o g 3 5 = 0.9710 H_3=-\frac{2}{5}log\frac{2}{5}-\frac{3}{5}log\frac{3}{5}=0.9710 </math>H3=−52log52−53log53=0.9710
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H ′ = 5 14 H 1 + 4 14 H 2 + 5 14 H 3 = 0.6936 H'=\frac{5}{14}H_1+\frac{4}{14}H_2+\frac{5}{14}H_3=0.6936 </math>H′=145H1+144H2+145H3=0.6936
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 信息增益 = 0.9403 − 0.6936 = 0.2467 信息增益=0.9403-0.6936=0.2467 </math>信息增益=0.9403−0.6936=0.2467
局限:信息增益偏向取值较多的特征
原因:当特征的取值较多时 ,根据此特征划分更容易得到纯度更高的子集,因此划分之后的熵更低,由于划分前的熵是一定的,因此信息增益更大,因此信息增益比较偏向取值较多的特征。(比如ID类特征,如果根据ID划分的话,每个人的ID都是不同的,那么每个子集的熵都为0,那么信息增益就很大了。)
C4.5算法
算法用信息增益率 选择特征,在树的构造过程中会进行剪枝操作优化,能够自动完成对连续属性的离散化处理;在选择分割特征时选择信息增益率最大的特征。
为了解决信息增益的局限,引入了信息增益率的概念。分支过多容易导致过拟合,造成不理想的后果。定义决策指标=信息增益/特征本身的熵。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H 0 = 0.9403 , H 1 = 0.9710 , H 2 = 0 , H 3 = 0.9710 H_0=0.9403,H_1=0.9710,H_2=0,H_3=0.9710 </math>H0=0.9403,H1=0.9710,H2=0,H3=0.9710
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H ′ = 5 14 H 1 + 4 14 H 2 + 5 14 H 3 = 0.6936 H'=\frac{5}{14}H_1+\frac{4}{14}H_2+\frac{5}{14}H_3=0.6936 </math>H′=145H1+144H2+145H3=0.6936
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> H 0 ′ = − ( 5 14 l o g 5 14 + 4 14 l o g 4 14 + 5 14 l o g 5 14 ) = 1.5774 H_0'=-(\frac{5}{14}log\frac{5}{14}+\frac{4}{14}log\frac{4}{14}+\frac{5}{14}log\frac{5}{14})=1.5774 </math>H0′=−(145log145+144log144+145log145)=1.5774
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 信息增益率 = H ′ / H 0 ′ = 0.1566 信息增益率=H'/H_0'=0.1566 </math>信息增益率=H′/H0′=0.1566
既然信息增益可以计算,为什么C4.5还使用信息增益率:
在使用信息增益的时候,如果某个特征有很多取值,使用这个取值多的特征会得到大的信息增益,这个问题是出现很多分支,将数据划分更细,模型复杂度更高,出现过拟合的几率更大。使用信息增益比就是为了解决偏向于选择取值较多的特征的问题。使用信息增益率对取值多的特征加上的惩罚,对这个问题进行校正。
信息增益率本质:是在信息增益的基础上乘上一个惩罚系数。特征个数较多时,惩罚参数较小;特征个数较少时,惩罚参数较大。
Gini系数和CART算法
使用Gini作为分割属性选择的标准,选择Gini最大的作为当前数据集的分割属性。
Gini:表示在样本集合中一个随机选中的样本被分错的概率
Gini指数越小表示集合中被选中的样本被分错的概率越小,也就是说集合的纯度越高,反之,集合越不纯。
Gini指数(Gini不纯度)=样本被选中的概率*样本被分错的概率
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> G i n i ( p ) = ∑ k = 1 K p k ( 1 − p k ) = 1 − ∑ k = 1 K p k 2 = 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 Gini(p)=\sum_{k=1}^Kp_k(1-p_k)=1-\sum_{k=1}^Kp_k^2=1-\sum_{k=1}^K(\frac{|C_k|}{|D|})^2 </math>Gini(p)=k=1∑Kpk(1−pk)=1−k=1∑Kpk2=1−k=1∑K(∣D∣∣Ck∣)2
- Pk表示选中的样本属于k类别的概率,被错分的概率为1-Pk
- 样本集合中有K个类别,一个随机选中的样本可属于这K个类别中的任意一个
- 当样本属于每一个类别的概率都相等即均为1/k时,Gini系数最大,不确定度最小
CART决策树又称分类回归树。当CART是分类树时,采用Gini值作为结点分裂的依据;当CART为回归树时,采用MSE作为结点分裂的依据。
CART算法由以下两步组成:
- 决策树生成:基于训练数据集生成决策树,生成的决策树要尽量大
- 决策树剪枝 :用验证数据集对已生成的树进行剪枝并选择最优子树,这时用损失函数最小作为剪枝的标准。
Gini指数和信息熵都表示数据不确定性,为什么CART使用Gini指数
信息熵logK都是值越大,数据的不确定性越大。信息熵需要计算对数,计算量大;信息熵是可以处理多个类别,Gini指数就是针对两个类计算的,由于CART树是一个二叉树,每次都是选择yes or no进行划分,从这个角度也是应该选择简单的Gini指数进行计算。
Gini指数存在的问题?
Gini指数偏向于多值属性。当类数较大时,Gini指数求解比较困难;Gini指数倾向于支持在两个分区中生成大小相同的测试
ID3 vs C4.5 vs CART
ID3 | C4.5 | CART | |
---|---|---|---|
分叉情况 | 多叉树 | 多叉树 | 二叉树 |
应用类型 | 分类树 | 分类树 | 分类和回归树 |
生成过程特征是否复用 | 不复用 | 不复用(离散型特征)和复用(连续型特征) | 复用 |
特征选择方式 | 信息增益 | 信息增益比 | 分类树:Gini 回归树:MSE |
优点 | 产生的规则易于理解;准确率较高;实现简单 | ||
缺点 | 1、不能对连续数据进行处理,只能通过连续数据离散化进行处理 2、采用信息增益进行数据分裂容易偏向取值较多的特征,准确性不如信息增益率 3、缺失值不好处理 4、没有采用剪枝,决策树的结构可能过于复杂,出现过拟合 | 1、对数据进行多次顺序扫描和排序,效率较低 2、只适合小规模数据集,需要将数据放到内存中 |
C4.5算法改进 | 将连续的特征离散化,取相邻两样本值的平均值,其中第i个划分点 |
---|---|
采用信息增益率的方法,它是信息增益和特征熵的比值,特征数较多的特征对应的特征熵越大,它作为分母,可以校正信息增益偏向取值较多的特征的问题 | |
主要需要解决的是两个问题 一是在样本某些特征缺失的情况下选择划分的属性 对于第一个子问题,对于某一个有缺失特征值的特征A。C4.5的思路是将数据分成两部分,对每个样本设置一个权重,然后划分数据,一部分是有特征值A的数据D1,另一部分是没有特征A的数据D2,然后对于没有缺失特征A的数据集D1来和对应的A特征的各个特征值一起计算加权权重后的信息增益比,最后乘上一个系数,这个系数是无特征A缺失的样本加权后所占加权总样本的比例 | |
二选定了划分属性,对于在该属性上缺失特征的样本的处理 对于第二个子问题,可以将缺失特征的样本同时划分入所有的子节点。不过将该样本的权重按各个子节点样本的数量比例来分配。比如缺失特征A的样本a之前权重为1,特征A有3个特征A1,A2,A3。3个特征值对应的无缺失A特征的样本个数为2,3,4。则a同时划分入A1,A2,A3。对应权重调节为2/9,3/9,4/9 | |
引入了正则化系数进行初步的剪枝,剪枝有两种: 预剪枝:在构造过程中,当某个节点满足剪枝条件,则直接停止此分支的构造 后剪枝:先构造完成完整的决策树,再通过某些条件遍历树进行剪枝 |
决策树
定义:决策树就是一棵树,其中根节点和内部节点是输入特征的判定条件,叶子节点就是最终结果。
其损失函数通常是正则化的极大似然函数;
目标:以损失函数为目标函数的最小化。
算法通常是一个递归的选择最优特征,并根据该特征对训练数据进行分割,使得对各个子数据集有一个最好的分类过程。
判断数据集'纯'的指标有三个:
- Gini指数
- 熵
- 错误率
决策树的数据split原理或者流程
- 将所有样本看作一个节点
- 根据纯度量化指标,计算每一个特征的纯度,根据最不纯的特征进行数据划分
- 重复上述步骤,直到每一个叶子节点都足够纯或者达到停止条件
构造决策树的步骤
- 特征选择
- 决策树的生成(包括预剪枝)------只考虑局部最优
- 决策树的剪枝(后剪枝)------只考虑全局最优
决策树算法中如何避免过拟合和欠拟合
-
过拟合:
- 选择能够反映业务逻辑的训练集去产生决策树;
- 剪枝操作(预剪枝和后剪枝);
- k折交叉验证
-
欠拟合:
- 增加树的深度;
- 随机森林RF
决策树怎么剪枝
- 预剪枝 :在构造决策树的过程中加入限制,比如控制叶子节点最少的样本个数、树的最大深度,提前停止;
- 后剪枝 :在决策树构造完成之后,根据加上正则化的结构风险最小化自下向上进行的剪枝操作 。损失函数加上惩罚项(叶子节点个数)
剪枝的目的是防止过拟合,是模型在测试数据上表现良好,增强鲁棒性
决策树的优缺点
-
优点
- 决策树模型可读性好,具有描述性,有助于人工分析
- 效率高,决策树只需要一次性构建,反复使用,每一次预测的最大计算次数不超过决策树的深度
-
缺点:
- 即使做了预剪枝,它也经常过拟合,泛化性能很差
- 对中间值的缺失敏感
- ID3算法计算信息增益时结果偏向数值多的特征
如果特征很多,决策树中最后没有用到的特征一定无用吗?
不是。从两个角度考虑:
- 一是特征替换性,如果已经使用的特征A和特征B可以替代特征C,特征C可能就没有被使用,但是如果把特征C单独拿出来训练,依然有效。
- 二是决策树的每一条路径就是计算条件概率的条件,前面的条件如果包含了后面的条件,只是这个条件在这颗树中是无用的,如果把这个条件拿出来也是可以帮助分析的。
决策树怎么做回归
给回归定义一个损失函数,比如L2损失,可以把分叉结果量化;最终的输出值是分支下的样本均值
决策树算法的停止条件
- 最小节点数:当节点的数据量小于一个指定的数量时,不继续分裂。两个原因:一是数据量少时,再做分裂容易强化噪声数据的作用;二是降低树生长的复杂性。提前结束分裂一定程度上有利于降低过拟合的影响。
- 熵或Gini值小于阈值:当熵或Gini值过小时,表示数据的纯度比较大,如果熵或者Gini值小于一定程度,节点停止分裂
- 决策树的深度达到指定的条件:决策树的深度是所有叶子节点的最大深度,当深度到达指定的上限大小时,停止分裂
- 所有特征已经使用完毕,不能继续进行分裂
代码实战
python
# 导入所需的库和模块
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error
from sklearn.tree import export_graphviz
import pydot
# 加载波士顿房屋价格数据集
boston = load_boston()
# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2, random_state=42)
这里从决策树回归角度来进行代码实战,首先加载波士顿房屋的价格数据集,并且划分训练数据集和测试数据集
python
# 创建决策树回归模型
regressor = DecisionTreeRegressor(max_depth=4)
# 训练模型
regressor.fit(X_train, y_train)
接着创建决策树回归模型,并且训练
python
# 预测
y_pred = regressor.predict(X_test)
# 计算平均绝对误差和均方根误差
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
print("Mean Absolute Error:", mae)
print("Mean Squared Error:", mse)
## Mean Absolute Error: 2.630697886796957
## Mean Squared Error: 10.747180683038659
最后进行预测,并计算MAE和MSE指标