1-2 决策树节点划分时的特征选择依据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1-2 决策树节点划分时的特征选择依据相关的知识,希望对你有一定的参考价值。

参考技术A 依据不同的决策树算法,在划分子节点时进行特征选择的依据有信息增益、信息增益比(又称信息增益率)、基尼系数三种。依次阐述如下:

0. 什么是信息熵?

如果没有学过信息论等与信息理论相关的书,初看信息熵是会有点懵逼的。在机器学习领域,信息熵的定义如下:

信息熵是度量样本集合纯度的一种最常用的指标,假设样本集合D的样本数一共有D个,一共有K类(标签),其中第k类样本所占的比例为pk,则该样本集的信息熵为:

有两点可以加强理解:① 信息熵是一个与类别标签相关,而与特征无关的量;②其实际反映的就是这个样本集中不同类别的样本的 占比情况 ,也就是前面所说的 纯度 。

如何直观的理解信息熵?可以从熵的最初概念出发,熵是表示体系混乱程度的度量,熵越大自然纯度就越小。

吊诡的地方在哪里呢?在于前面的信息二字,信息熵越大到底代表信息量越大还是信息量越小?如果我们把信息量理解的直观一点,两者是反着的,信息熵越大,能给我们利用的信息就越少。

举个简单的栗子,样本集D有10个人。如果是5个好人5个坏人,信息熵就会大于8个好人2个坏人的情况。

为什么呢?因为5:5的比例确实带不来任何信息,假设我们现在就只有这么个样本集,然后来一个新样本,我们判断这个新样本是个好人还是坏人?5:5的样本集告诉我们,有0.5的概率是好人0.5的概率是坏人,也就是跟随机抛硬币一样,无论我们最后给新样本定什么标签,都有50%的错误率。但假设我们的样本集是8:2,其它什么特征都不用,我们可以判断,这个新样本80%的概率是好人,20%的概率是坏人,所以我们应该无脑的把所有人都判断为好人,这样我们预计只有20%的错误率。

这就是信息熵发挥的作用,样本类别越均衡,就是纯度越小,信息熵越大,可用的信息就越少。

1. 信息增益

前面扯了这么多废话把信息熵弄明白,信息增益就简单多了。如果我们按照某个特征的取值,把原始样本集划分为若干个子集,然后用某种方式求一下这些子集的信息熵“之和”,我们希望什么,我们希望划分后的信息熵要减小得尽可能的多, 这个信息熵的减小量,就是信息增益 。

第一个问题:划分后的子集信息熵之和怎么算?按照信息熵定义,每个子集都能算一个信息熵出来,简单求个和吗?那肯定不行,毕竟还有个样本量的问题,把样本量考虑进去,就相当于给每个子集的信息熵配一个权重,这个权重就是这个子集的样本数占样本总数的比例,然后加权求个和,这就是划分子集后的信息熵求法。

用原始的信息熵减去上面这个划分后的信息熵,就是信息增益咯。再说一遍,信息增益就是信息熵的减小量。

补充点废话:信息增益大意味着什么?意味着划分后的样本集们普遍的信息熵较小,也就是纯度较大,纯度较大意味着什么,意味着划分后的各个子集有可能这个子集全是好人,那个子集全是坏人,这不正是我们想要的吗,我们要的恰恰就就是根据特征来有效判断人的好坏,所以选信息增益大的特征进行样本划分也就是理所当然的了。

使用信息增益来划分节点的决策树算法叫ID3算法

2. 信息增益比(率)

信息增益有什么问题?假设我们有两个特征可供选择,性别与年龄,其中性别的取值只有男和女两种,而年龄的取值有18、19、20、...、64、65几十个。这会带来什么问题呢?定性想一下,特征取值越多,划分后的各个子集就会越小,而越小的子集其分布就越有可能偏。还是按前面的栗子来说,10个人按性别划分成5个男人5个女人,而这两个子集里有分别都有好人和坏人,信息增益可能just soso,但如果按年龄分,假设10个人恰好是10个不同的年龄,那划分后每个子集里要么是一个好人要么是一个坏人,纯度杠杠的,信息增益杠杠的。但这是否代表年龄真的是个更好用得特征?并不是,这是因为我们的样本集终究是有限个样本构成的,当特征取值很多时,子集越小,越小就越有可能出现统计学意义上的偏差,从而使其信息增益看起来大。废话了这么多,想说明什么问题呢?就是 “依据信息增益划分子集”这个标准会偏爱可取值数多的特征,而这个特征在刻画样本时不一定强 。

为了平衡这一点,我们要设法对信息增益做个类似归一化的操作,让不同特征间能有可比性。归一化肯定要考虑特征取值数了,但直接把信息增益除以特征取值数就太简单粗暴了,因此我们再定义一个指标,这个指标称之为特征的固有值,整体上与特征的可取值数会正相关,定义如下:

使用特征a的信息增益除以特征a的固有值,就是信息增益比了,使用信息增益比来划分节点的决策树算法叫C4.5算法。

前面说过,信息增益会偏爱取值数较多的特征,那么信息增益比是不是一视同仁了呢?没有, 信息增益比会偏爱取值数较少的特征 (捂脸哭)。所以最机智的做法应该是设法结合两者。

3. 基尼系数

其实决策树的节点划分这个事儿吧,搞这么多指标出来自然有它的理由,但这些指标说来说去呢,为的都是一件事儿,那就是我们要 找到最有用的特征 来划分节点。那什么是最有用呢?就是 能最有效的区分样本的类别。 不管什么指标,本质上度量的都是这个事儿。

基尼系数自然也是如此了,基尼系数 反映了 从样本集中随机抽取两个样本,其类别标记不一致的概率,原始样本集的基尼系数这么算:

为毛说基尼系数反映了随机选取的两个样本类别不一致的概率呢?pk是不同类别的样本所占的比例,因此它们的和为1,一堆介于0~1之间的pk的平方和,什么时候最小?当所有的pk相等的时候平方和最小,这个可以用初中数学知识证明。而当每个类别所占的比例都一样的时候,随机抽取的两个样本不一样的概率最大。比如,在5个好人5个坏人里随机抽俩人,这俩人一个是好人一个是坏人的概率还是蛮大的,但如果在9个好人1个坏人里抽俩人,这俩人就有更大概率是两个好人。因此基尼系数度量的也是纯度,由于前面有个1-,基尼系数越大,意味着纯度越小(也意味着信息熵越大)。

理解了基尼系数和信息熵反应的本质是一样的之后,这事就好说了,信息增益是信息熵的减小量,对比想一下这儿就是用划分后基尼系数减小量咯?差不多,但不完全一样,这里是直接用了划分后基尼系数,哪个特征最小就用哪个。为毛呢?因为划分前大家都是一个基尼系数啊,划分后基尼系数最小,可不就是划分后基尼系数减小量最大嘛,所以是一回事。从这个角度来说,前面用信息增益最大也没必要,直接用划分后信息熵最小的那个就行了,效果是一样一样的。

使用基尼系数划分特征的决策树算法叫CART算法。CART的全称是classify and regression tree(分类和回归树),回归树是什么玩意,以后再说了。

以上就是决策树节点划分时特征选择所用的三个指标。

理解CART决策树

CART算法

原理

CART全称为Classification and Regression Tree。

回归树

相比ID3,CART遍历所有的特征和特征值,然后使用二元切分法划分数据子集,也就是每个节点都只会分裂2个分支。接着计算数据子集的总方差来度量数据子集的混乱程度,总方差越小数据子集越纯,最后选择总方差最小的划分方式对应的特征和特征值,而二元切分的依据就是将小于等于这个特征值和大于这个特征值的数据划分为两块。这里说的总方差一般就是通过数据子集的样本输出值的均方差 * 数据子集的样本个数来计算。最后的输出结果是取各叶子节点数据的中位数或均值。

分类树

相比ID3,CART一般选择基尼不纯度来代替信息增益的方式度量数据子集的不纯度。基尼不纯度越小,数据纯度越高。相比回归树,分类树对于离散或者连续特征的处理都是采用二元切分的方式,但是在数据子集的混乱程度的计算上,是用基尼不纯度替代总方差的方式。

基尼不纯度的定义:从一个数据集中随机选取子项,度量其被错误的划分到其他组里的概率。

先不着急理解这句话,先看下面对基尼不纯度的表达式的解释。

  • 假设一个数据集中有K个类别,第k个类别的概率为p_k, 则基尼系数的表达式为:
    技术图片
    上面的公式中,p_k表示第k个类别出现的概率,那么1-p_k显然就是当前数据集中,除了第k个类别以外的其他所有类别出现的概率,所以两者相乘就是当前数据集中,第k个类别和其他所有类别都出现的概率,这个概率越高,数据集越不纯。
    现在再看上面的定义,应该就好理解了吧。
  • 对于个给定的样本D,假设有K个类别, 第k个类别的数量为CkCk,则样本D的基尼系数表达式为:
    技术图片
  • 对于样本D,如果根据特征A的某个值a,把D分成D1和D2两部分,则在特征A的条件下,D的基尼系数表达式为:
    技术图片

算法库调用

在scikit-learn库中的决策树算法是使用了调优过的CART算法,既可以做分类,又可以做回归。

代码

分类树对应DecisionTreeClassifier,回归树对应DecisionTreeRegressor。代码示例和参数说明如下:

from sklearn.tree import DecisionTreeClassifier
clf_dt = DecisionTreeClassifier()
clf_dt.fit(train_X, train_y)
predictions_dt = clf_dt.predict(test_X)[:,None]

参数

参数 DecisionTreeClassifier DecisionTreeRegressor
criterion 特征选择标准。可以使用"gini"或者"entropy",前者代表基尼系数,后者代表信息增益。一般说使用默认的基尼系数"gini"就可以了,即CART算法。除非你更喜欢类似ID3, C4.5的最优特征选择方法。? 可以使用"mse"或者"mae",前者是均方差,后者是和均值之差的绝对值之和。推荐使用默认的"mse"。一般来说"mse"比"mae"更加精确。除非你想比较二个参数的效果的不同之处。
splitter 特征划分点选择标准。可以使用"best"或者"random"。前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random"? 同左。
max_features 划分时考虑的最大特征数。 可以使用很多种类型的值,默认是"None",意味着划分时考虑所有的特征数;如果是"log2"意味着划分时最多考虑log2Nlog2N个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑N??√N个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。一般来说,如果样本特征数不多,比如小于50,我们用默认的"None"就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。 同左。
max_depth ?决策树的最大深度。默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。 同左。
min_samples_split 内部节点再划分所需最小样本数。这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。?默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。 同左。
min_samples_leaf 叶子节点最少样本数。 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。?默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。
min_weight_fraction_leaf 叶子节点最小的样本权重和。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。?默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。 同左。
max_leaf_nodes 最大叶子节点数。通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。 同左。
class_weight 指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的"None" 不适用于回归树。
min_impurity_split 节点划分最小不纯度。这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶子节点?。 同左。
presort 数据是否预排序。这个值是布尔值,默认是False不排序。一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。如果样本量太大的话,反而没有什么好处。问题是样本量少的时候,我速度本来就不慢。所以这个值一般懒得理它就可以了。 同左。

决策树可视化

安装graphviz

可视化需要先安装graphviz,这是一个开源的图形可视化软件,官网:https://graphviz.gitlab.io,下载适合自己操作系统的文件即可。

如果是windows操作系统,可以点此下载安装包。安装完成记得设置一下环境变量将 xxx/Graphviz2.38/bin/加入PATH

安装python插件:

pip install graphviz
pip install?pydotplus

代码示例

from sklearn.datasets import load_iris
from sklearn import tree
import pydotplus
import os
# 如果执行程序总是找不到Graphviz命令,可以加入下面这行代码,注意修改路径为你的正确的Graphviz/bin目录的路径
os.environ["PATH"] += os.pathsep + 'H:/program_files/Graphviz2.38/bin'
# 训练模型
iris = load_iris()
clf = tree.DecisionTreeClassifier()
clf = clf.fit(iris.data, iris.target)
# 用pydotplus生成iris.pdf
dot_data = tree.export_graphviz(clf, out_file=None,
                                feature_names=iris.feature_names,
                                class_names=iris.target_names,
                                filled=True, rounded=True,
                                special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_pdf("iris.pdf")

查看pdf文件

技术图片

参考资料

https://www.cnblogs.com/pinard/p/6056319.html

https://blog.csdn.net/JJBOOM425/article/details/79997440

https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/tree/_tree.pyx

ok,本篇就这么多内容啦~,感谢阅读O(∩_∩)O。

技术图片

以上是关于1-2 决策树节点划分时的特征选择依据的主要内容,如果未能解决你的问题,请参考以下文章

决策树的部分理解

决策树与随机森林算法

决策树

机器学习算法基础+实战系列决策树算法

决策树(上)

决策树(decision tree)