【机器学习+python(8)】分类决策树的介绍与实现

欢迎关注大家关注微信公众号【哈希大数据】


       之前我们介绍过用逻辑回归根据鸢尾花萼片、花瓣的长度和宽度进行鸢尾花类别的判定;也通过朴素贝叶斯模型分享了如何根据男生专业和身高两大属性,判断其是否有女朋友。而本期我们将介绍另外一种有监督的机器学习分类模型----决策树(也可以实现基本的回归),重点介绍决策树的基本原理和实现,并且借助python的sklearn库中的决策树算法实现上述两类数据分类展示。

决策树的基本原理

       想必大家都有疑问,好多机器学习算法均可实现分类,那不同之处是什么呢?对于逻辑回归,我们已知它是基于线性模型,通过对数据特征给予权重相加得到新的一个回归值,再进行Sigmoid变换将回归值约束在(0,1)之间,进而通过值的大小判断所属的类型(一般情况实现的是线性分割,输入特征x与logit之间是线性的,除非对x进行多维映射)。

       而朴素贝叶斯模型则是基于贝叶斯定理、条件概率、特征独立分布的,根据样本特征计算其属于特定类别的概率,然后根据概率大小确定其最终的分类结果。

      决策树算法简单来说就是带有判断规则(if-then)的一种树,可以依据树中的决策规则来预测未知样本的类别或数值(分类和回归)。其核心是对数据进行一个一个特征的筛选和处理,并且对特征阈值实现非线性分割,根据得出的抉择结果依次建立树模型。其主要优点是树形模型更接近人的思维方式,分类速度快,易于理解,可产生可视化、可解释的的分类规则。

      比如:当我们想要出门时,会根据降雨、雾霾、气温、活动范围是室内还是室外等等特征综合进行考虑和判断,做出最后决定。下图是一个简单判断是否出门的4层决策树分类结果。结果表明,下雨时,一定不出门;而如果不下雨却有雾霾也不会出门。。。。。。 

        整个分类结果 一目了然,而且结构像一棵树,有分叉的节点(数据特征)和树叶(判定结果)。其中根节点(图中降雨属性)表示在此次分类中筛选出的最重要的特征;分叉处的父节点和子节点表示目标的某一个特征或属性,而结果节点也称为叶子节点,是完成判断后产生的最终决策结果(出门or不出门)。

        看到这里可能会有疑问,为什么要选择降雨作为决策树的根节点,而不是雾霾情况或气温等?****而对于时间属性(连续型)的分割,为何是以18°,30°,35°为临界?这就是实现决策树过程要解决的核心问题:如何依次选择数据的属性;如何计算每个属性的决策规则(完成数据的分裂);什么时候可以停止分裂(防止过拟合)。下面详细通过决策树算法来解决这些疑问,并通过实例完成建树和剪枝。

决策树算法

决策树算法简介

       决策树算法通常是递归地选择最优特征,也就是会把每个特征都计算一遍,选取能够使分类分的最好的一个特征,然后用这个最优特征构建根结点,依次对数据集进行分割。比如该特征为离散型有几种值就分割为几个子集;而如果特征是连续型的则通过离散化处理后得到分割阈值后再分割子集;每个子集再分别递归调用特征选择方法,依次返回结点,返回的结点也就是上一层的子结点;直到所有特征都已经用完,或者数据集只有一维特征时停止。

       为了防止过拟合问题,计算每个节点的分类错误,进行剪枝处理。(先剪枝,在构造过程中,当某个节点满足剪枝条件,则直接停止此分支的构造;后剪枝,先构造完成完整的决策树,再通过某些条件遍历树进行剪枝。)

       一般而言,随着划分过程不断进行,我们希望决策树的分支节点所包含的样本尽可能属于同一类别(也就是当下雨时得出的分类结果都是不出门),即节点的“纯度”越来越高。就是保证目标变量要分得足够开(将y=出门和y=不出门两种情况按照不同天气特征判定尽可能分离)。

       此时我们将寻找最纯净的划分方法,决策树中常用的方法有ID3、C4.5、和CART,其中ID3算法使用信息增益作为不纯度;C4.5算法使用信息增益率作为不纯度;CART算法对回归树用平方误差最小化准则,对分类树用基尼指数(Gini index)最小化准则,进行特征选择,生成决策树。

   **来,咱继续唠~~~**

      鉴于ID3算法要求数据特征为离散值,而且特征中的类型数量会影响信息增益值;而c4.5算法生成的多叉树,运算强度较高;因此我们直接以CART算法实现二叉分类树为例,进行完整介绍:

      假设有K个类的样本D(A属性,Y类别)属于第i类的概率为:pi,则分类后的基尼指数为:

       它表示训练数据的不确定性,值越大表明特征所对应的类型越不确定。如二分类问题中,假设样本x属于类别1的概率为p,则基尼指数为:Gini(x)=2p(1-p),当两类情况的可能均为1/2时,其不确定性最大为1/2。对于个给定的样本D,假设有K个类别, 第k个类别的数量为Ck,则样本D的基尼系数为:

    ![image](http://upload-images.jianshu.io/upload_images/11382441-f06c757bf4876374?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

      根据数据特征A将样本D的空间分为两块y1,y2。两块样本数据大小分别为:D1,D2。则在特征A的条件下,基尼系数为:

     ![image](http://upload-images.jianshu.io/upload_images/11382441-c6f41021e8548b0d?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

      选择使该基尼系数最小的属性A,作为父节点,得出对应的子节点或叶子节点。然后依次递归其他所有属性,依次选择基尼系数最下的属性,作为优先判断的属性.其中如果属性是连续的数据,将对这些数据进行离散化处理,处理的基本思路是:

    (1)选取该属性的所有n个数值,取相邻两样本值的中位数,一共取得n-1个划分点,对于这n-1个点,分别计算以该点作为二元分类点时的基尼系数

    (2)选择基尼系数最小的点作为该连续特征的二元离散分类点。

       比如取到的基尼系数最小的点为at,则小于at的值为类别1,大于at的值为类别2,这样我们就做到了连续特征的离散化。其中这些属性后面还可以参与子节点的产生选择过程。

       关于建树和剪枝

          建树具体流程为:

输入:训练集D,基尼系数的阈值,样本个数阈值。

输出:分类决策树T。

流程:(根节点依次往下)

  1. 对于当前节点的数据集为D,如果样本个数小于阈值或者没有特征,则返回决策子树,当前节点停止递归。

  2. 计算样本集D的基尼系数,如果基尼系数小于阈值,则返回决策树子树,当前节点停止递归。

          3.计算当前节点现有的各个特征值对数据集D的基尼系数。

         4.选择基尼系数最小的特征A和对应的特征值a。根据这个最优特征和最优特征值,把数据集划分成两部分D1和D2,同时建立当前节点的左右节点,做节点的数据集D为D1,右节点的数据集D为D2.

  1. 对左右的子节点递归的调用1-4步,生成决策树。

对于生成的决策树做预测的时候,假如测试集里的样本A落到了某个叶子节点,而节点里有多个训练样本。则对于A的类别预测采用的是这个叶子节点里概率最大的类别。

停止分裂的条件

(1)最小节点数

当节点的数据量小于一个指定的数量时,不继续分裂。两个原因:一是数据量较少时,再做分裂容易强化噪声数据的作用;二是降低树生长的复杂性。提前结束分裂一定程度上有利于降低过拟合的影响。

(2)基尼值(信息熵)小于阀值

基尼值大小表示数据的复杂程度,当熵或者基尼值过小时,表示数据的纯度比较大,如果熵或者基尼值小于一定程度时,节点停止分裂。

(3)决策树的深度达到指定的条件

节点的深度可以理解为节点与决策树跟节点的距离,如根节点的子节点的深度为1,因为这些节点与跟节点的距离为1,子节点的深度要比父节点的深度大1。决策树的深度是所有叶子节点的最大深度,当深度到达指定的上限大小时,停止分裂。

(4)所有特征已经使用完毕,不能继续进行分裂

被动式停止分裂的条件,当已经没有可分的属性时,直接将当前节点设置为叶子节点。

决策数的Python实现

# 构建模型def tree_module(trainData,labels):    decision_tree = tree.DecisionTreeClassifier(max_depth=4)    decision_tree_one = decision_tree.fit(trainData, labels)    return decision_tree_one# 绘制决策树图def pic_tree(decision_tree,filename,columns,theclass,save_path):    # 保存模型    with open (filename, 'w') as f:        f = tree.export_graphviz (decision_tree, out_file=f)    dot_data = tree.export_graphviz (decision_tree, out_file=None, feature_names=columns,                                     class_names=theclass, filled=True, rounded=True, special_characters=True)    graph = pydotplus.graph_from_dot_data (dot_data)

分类结果

鸢尾花分类结果:

image

"能找到对象的男生"特征分类结果:

image

结果说明:

从决策树的结果分类来看:对于区分鸢尾花类型,花瓣的宽度是最核心属性。而且在决策树深度为4的条件下:仅有3个样本未完全区分开,其余的gini指数都为0,保证了完全区分。

而在根据男生特征对是否有女朋友的判断中,不同于我们上次贝叶斯分类得出的判断,只要是数学专业的男生无论身高特征几乎都是有女朋友的,而在分类树中身高的高低是最重要的判定因素,更加符合我们的常识判断。

猜你喜欢

转载自blog.csdn.net/hashdata2018/article/details/80640545
今日推荐