一、信息论基础
树具有天然的分支结构。对于分类问题而言,决策树的思想是用节点代表样本集合,通过某些判定条件来对节点内的样本进行分配,将它们划分到该节点下的子节点,并且要求各个子节点中类别的纯度之和应高于该节点中的类别纯度,从而起到分类效果。
节点纯度反映的是节点样本标签的不确定性。当一个节点的纯度较低时,说明每种类别都倾向于比较均匀的频率出现,从而我们比较难在这个节点上得到关于样本标签的具体信息,其不确定性较高。当一个节点的纯度很高时,说明有些类别倾向于比较高的频率出现,从而我们能够更有信心把握这个节点样本标签的具体信息,即确定性较高。
信息熵:熵是衡量信息量大小的一个数值,信息熵描述的是一个随机变量的不确定程度,不确定性越大熵值越大。即 对随机事件的信息量求期望。
联合熵:两个随机变量的X、Y的联合分布,可以称为联合熵,H(X,Y)。
条件熵:H(X,Y) - H(Y) 表示(X,Y)发生所包含的熵减去Y单独发生所包含的熵:在Y发生的前提下,X发生新带来的熵。
信息增益:即节点分裂之后带来了多少不确定性的降低或纯度的提高。
参考:https://www.cnblogs.com/little-YTMM/p/5582271.html
二、分类树的节点分裂
对每个节点进行分裂决策时,会抽出max_features个特征进行遍历以比较信息增益的大小。特征的类别可以分为三种情况讨论:类别特征、数值特征和含缺失值的特征。对类别特征而言,给定一个阈值,树的每一个节点会选择最大信息增益对应的特征进行分裂,直到所有节点的相对最大信息增益小于阈值,这种生成算法为ID3算法。在sklearn中,min_impurity_decrease即为阈值。
C4.5算法在ID3算法的基础上作出了改进,包括但不限于:处理数值特征、处理含缺失值的特征、使用信息增益比代替信息增益以及给出树的剪枝策略。
在处理节点数值特征时,可以用两种方法来将数值特征通过分隔转化为类别,它们分别是最佳分隔法和随机分隔法,分别对应sklearn中的splitter参数的best和random.
C4.5算法处理缺失数据的思想非常简单,样本的缺失值占比越大,那么对信息增益的惩罚就越大,因为缺失值本身就是一种不确定性成分。
前面所说的都是单个节点如何选取特征进行分裂,但没有涉及到树节点的分裂顺序。在sklearn中提供了两种生长模式,它们分别被称为深度优先生长和最佳增益生长,当参数max_leaf_nodes使用默认none时使用前者,当它被赋予某个数值时使用后者。
深度优先生长采用深度优先搜索的方法:若当前节点存在未搜索过的子节点,则当前节点跳转到子节点进行分裂决策;若当前节点为叶节点,则跳转到上一层节点,直到根节点不存在未搜索过的子节点为止。当决策树使用最佳增益生长时,每次总是选择会带来最大相对信息增益的节点进行分裂,直到叶节点的最大数量达到max_left_nodes.
三、CART决策树
cart(classification and regression tree)是一棵二叉树,既能处理分类问题,又能处理回归问题。但是在sklearn中没有实现处理类别特征和处理缺失值的问题,前者是因为多个类别的特征会产生多叉树,后者因为sklearn认为用户应该自己决定缺失值的处理而不是交给模型来决定。
对于回归树而言,每个叶节点输出的不再是类别而是数值,其输出值为该叶节点所有样本标签的均值。在每次分裂时,我们希望不同的子节点之间的差异较大,但每个子节点内部的差异较小。此时,分割策略仍然可以采用随机分割法或者最佳分隔法,只是现在不再以熵来评价子节点的纯度,而是使用均方误差或平均绝对误差来替换熵和条件熵的位置,从而引出基尼系数的信息增益。
常见问题整理:
(1)假设需要处理一个分类问题,请问对输入特征进行归一化会对树模型的类别输出产生影响吗?请解释原因
不会产生影响,理由如下:
使用归一化的目的是因为各个特征之间数值大小不同使得它们对某些模型(通过梯度下降法求解的模型通常是需要归一化的),比如神经网络的输出和损失计算的影响不同,这样反向传播时会偏向于数值比较大的特征,这样是不合理的。 因为在没有任何先验知识的情况下,各个特征应该一视同仁。但是,树模型是直接利用数据的信息熵来建立的,不需要计算损失函数并反向传播,因此各个特征之间数值的大小不同不会影响 它的建模过程。换句话说,神经网络里数据的数值会直接和权重相乘,进行计算,树模型不会直接使用数值本身,而是使用它出现的概率。
(2)C4.5算法中,如果将信息增益的系数替换为(1-r^2),请问对缺失值时增强了还是削弱了惩罚?
将系数替换为1-r^2后削弱了对缺失值的惩罚,因为缺失值的比例r<=1, 平方之后缺失比例变小了,样本的不确定性变小了。
(3)决策树的生长策略假如由深度优先生长改成广度优先生长,其他参数保持不变的情况下,两个模型对应的结果输出一样吗?
不一样,
(4)在一般的机器学习问题中,总是会通过一组参数来定义模型的损失函数,并且在训练集上以最小化该损失函数为目标进行优化,那么对于决策树而言,模型优化的目标是什么?
优化的目标是提升度,类似于提升节点的纯度,提升度越高越好。
(5)决策树三种算法的有何异同?
(6)什么是信息增益,衡量了什么指标,有什么缺陷?
信息增益:即节点分裂之后带来了多少不确定性的降低或纯度的提高。
一般来说,通过一种划分方式带来的纯度提升越大,信息增益就越高。ID3算法以信息增益为准则来选择决策树划分属性。值多的属性更有可能会带来更高的纯度提升,所以信息增益的比较偏向选择取值多的属性。
可能会带来一个不好的结果,如果选择唯一ID作为划分属性,那么会得到n个类别,每个类别都只包含一个样本,每个节点的纯度都是最高的,纯度提升也是最大的,带来的信息增益也是最高的。但是这样的划分是没有意义的。
(7)sklearn 决策树中的random_state参数控制了哪些步骤的随机性?
random_state参数主要是为了保证每次都分割一样的训练集和测试集,大小可以是任意一个整数,在调参缓解,只要保证其值一致即可。
因为同一算法模型在不同的训练集和测试集的会得到不同的准确率,无法调参。所以在sklearn 中可以通过添加random_state,通过固定random_state的值,每次可以分割得到同样训练集和测试集。
(8)决策树如何处理连续变量和缺失变量?
处理连续型属性(例如西瓜的成熟度、学生成绩)时,需要将其离散化,将连续型属性的值划分到不同的区间(类似于二叉排序树),比较各个分裂点的Gain值的大小。
在C4.5决策树算法中,采用二分法处理连续型属性。
当属性值有缺失时主要解决两个问题:
在有属性值有缺失的情况下,如何选择最优属性?这时候需要重新定义信息增益计算方式来选择最优属性;
给定划分属性后,训练集中属性值含有缺失值,如何划分样本?
若样本属性已知,则将样本划分到与其取值相同的子节点中,权值w不变
若样本属性缺失,则将该样本同时划分到所有子节点,样本权值也要相应的调整;
(9)基尼系数是什么?为什么要在cart中引入它?
基尼值 Gini(D) 反映了从数据集中随机抽取两个样本,其类别标记不一致的概率。当数据集的纯度越高,每次抽到不同类别标记的概率越小。打个比方,在一个袋子里装100个乒乓球,其中有99个白球,1个黄球,那么当我们随机抽取两个球的时候,很大概率是抽到两个白球。所以数据集D的纯度可以用基尼值来度量,基尼指数是针对于属性定义的,其反映的是,使用属性a进行划分后,所有分支中(使用基尼值度量的)纯度的加权和。
在ID3算法中我们使用了信息增益来选择特征,信息增益大的优先选择。在C4.5算法中,采用了信息增益比来选择特征,以减少信息增益容易选择特征值多的特征的问题。但是无论是ID3还是C4.5,都是基于信息论的熵模型的,这里面会涉及大量的对数运算。所以为了简化模型的同时也不至于完全丢失熵模型,CART分类树算法使用基尼系数来代替信息增益比,基尼系数代表了模型的不纯度,基尼系数越小,则不纯度越低,特征越好。这和信息增益(比)是相反的。
(10)什么是树的预剪枝和后剪枝,具体是如何操作的?
树的剪枝就是剪掉树的一些枝叶,考虑大决策树的枝代表着逻辑判断,也代表着分类后的子集。决策树的剪枝就是删掉一些不必要的逻辑判断,并且将子集合并。这样确实会造成在训练集上子集不纯的现象,但是因为我们最终目标是模型在测试集上的效果,所以牺牲在训练集上的效果换取解决测试集的过拟合问题这样的做法也是值得的。决策树剪枝可以分为两类,预剪枝(Pre-Pruning)和后剪枝(Post-Pruning)。
PrePrune:预剪枝,及早的停止树增长;PostPrune:后剪枝,在已生成过拟合决策树上进行剪枝,可以得到简化版的剪枝决策树。
预剪枝:就是在生成决策树的同时进行剪枝。正常决策树的生成是只要有信息增益就要进行分支,换句话可以说所有决策树的构建方法,都是在无法进一步降低熵的情况下才会停止创建分支的过程,为了避免过拟合,可以设定一个阈值,熵减小的数量小于这个阈值,即使还可以继续降低熵,也停止继续创建分支。预剪枝就是设定一个阈值,比如只有在信息增益大于这个阈值的时候(也即是在分类后的信息混乱程度减小程度大于一定标准的时候)才进行分类。如果在信息增益过小的情况下,即使存在信息增益的现象,也不会对其进行分支。预剪枝的思想比较简单,但在实际应用中,预剪枝的表现并不是很好。所以,目前我们基本都是使用后剪枝方法。
预剪枝依据:
- 作为叶结点或作为根结点需要含的最少样本个数
- 决策树的层数
- 结点的经验熵小于某个阈值才停止
后剪枝:就是在决策树构造完成后进行剪枝。剪枝的过程是对拥有相同父节点的一组节点进行检查,如果将其合并,熵增小于某一阈值,那么这一组节点可以合并一个节点。如果将其合并后熵增大于这个阈值,那么说明将其分枝是合理的。后剪枝就是删除一些子树,然后用其叶节点代替。这个叶节点代表的子集不一定都是“纯”的。那么,这个叶子节点所标识的类别通过大多数原则确定。大多数原则就是指这个叶节点所代表的子集中大多数的类别来表示这个叶节点。剪枝的过程是对拥有同样父节点的一组节点进行检查,判断如果将其合并,熵的增加量是否小于某一阈值。如果确实小,则这一组节点可以合并一个节点,其中包含了所有可能的结果。后剪枝是目前最普遍的做法。
常用的后剪枝算法有五种,REP、PEP、MEP、CCP算法和后规则修剪方法。如果训练数据较少,PEP算法表现出良好的预测精度,随着数据规模的增大,使用REP和CCP剪枝方法得到的决策树的分类性能和预测精度明显提高。
参考:https://www.cnblogs.com/bonheur/p/12469858.html
四、决策树相关python相关方法总结
1、sklearn.tree
.DecisionTreeClassifier 决策树分类器
class sklearn.tree.DecisionTreeClassifier(*, criterion='gini', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, class_weight=None, ccp_alpha=0.0)
(1)参数解析
criterion{“gini”, “entropy”}, default=”gini”
这个函数是来衡量分裂的质量,支持基尼系数(基尼纯度)和熵(信息增益);
splitter{“best”, “random”}, default=”best”
这个方法主要是用来选择节点分裂,分别对应最佳分隔法和随机分隔法;
max_depth: int, default=None
表示树的最大深度,默认none时,节点将会扩展到所有的叶子都是纯的或所有的叶子包含少于min_samples_split个样本.
min_samples_split :int or float, default=2
分裂一个内部节点所需的最小样本数。
min_samples_leaf:int or float, default=1
叶节点所需的最小样本数。 任何深度的分裂点只有在左右分支中至少留下 min_samples_leaf 训练样本时才会被考虑。 这可能具有平滑模型的效果,尤其是在回归中;
https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html