飞鸟各投林

导航

第三章:决策树

本章内容
□ 决策树简介
□ 在数据集中度量一致性
□ 使用递归构造决策树
□ 使用matplotlib绘制树形图


      我们经常使用决策树处理分类问题近来的调查表明决策树也是最经常使用的数据挖掘算法。它之所以如此流行,一个很重要的原因就是使用者基本上不用了解机器学习算法,也不用深究它是如何工作的。

      第2章介绍的k-近邻算法可以完成很多分类任务,但是它最大的缺点就是无法给出数据的内在含义,决策树的主要优势就在于数据形式非常容易理解。

      现在我们已经大致了解了决策树可以完成哪些任务,接下来我们将学习如何从一堆原始数据中构造决策树。首先我们讨论构造决策树的方法,以及如何编写构造树的python代码;接着提出一些度量算法成功率的方法;最后使用递归建立分类器,并且使用matplotlib绘制决策树图。构造完成决策树分类器之后,我们将输人一些隐形眼镜的处方数据,并由决策树分类器预测需要的镜片类型。


 3.1 决策树的构造

决策树
优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配问题
适用数据类型:数值型和标称型

      在构造决策树时,我们需要解决的第一个问题就是,当前数据集上哪个特征在划分数据分类时起决定性作用。为了找到决定性的特征,划分出最好的结果,我们必须评估每个特征。完成测试之后,原始数据集就被划分为几个数据子集。这些数据子集会分布在第一个决策点的所有分支上。如果某个分支下的数据属于同一类型,则当前无需阅读的垃圾邮件已经正确地划分数据分类,无需进一步对数据集进行分割。如果数据子集内的数据不属于同一类型,则需要重复划分数据子集的过程。如何划分数据子集的算法和划分原始数据集的方法相同,直到所有具有相同类型的数据均在一个数据子集内。
      创建分支的伪代码函数createBranch ()如下所水:

检测数据集中的每个子项是否属于同一分类:
   If so return 类标签;
   Else
       寻找划分数据集的最好特征
       划分数据集
       创建分支节点
       for每个划分的子集
            调用函数createBranch ()并增加返回结果到分支节点中
return分支节点

      上面的伪代码createBranch ()是一个递归函数,在倒数第二行直接调用了它自己。后面我们将把上面的伪代码转换为python代码,这里我们需要进一步了解算法是如何划分数据集的。

     一些决策树算法采用二分法划分数据,本书并不采用这种方法。如果依据某个属性划分数据将会产生4个可能的值,我们将把数据划分成四块,并创建四个不同的分支。本书将使用ID3算法划分数据集,该算法处理如何划分数据集,何时停止划分数据集(进一步的信息可以参见http://en.wikipedia.org/wiki/ID3_algorithm。每次划分数据集时我们只选取一个特征属性,如果训练集中存在20个特征,第一次我们选择哪个特征作为划分的参考属性呢?
       表3-1的数据包含5个海洋动物,特征包括:不浮出水面是否可以生存,以及是否有脚蹼。我们可以将这些动物分成两类:鱼类和非鱼类。现在我们想要决定依据第一个特征还是第二个特征划分数据。在回答这个问题之前,我们必须采用量化的方法判断如何划分数据。下一小节将详细讨论这个问题。


 

3.1.1 信息増益

       划分数据集的大原则是:将无序的数据变得更加有序。我们可以使用多种方法划分数据集,但是每种方法都有各自的优缺点。组织杂乱无章数据的一种方法就是使用信息论度量信息,信息论是量化处理信息的分支科学。我们可以在划分数据之前使用信息论量化度量信息的内容。
      在划分数据集之前之后信息发生的变化称为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。在可以评测哪种数据划分方式是最好的数据划分之前,我们必须学习如何计算信息增益。集合信息的度量方式称为香农熵或者简称为熵,这个名字来源于信息论之父克劳德•香农。

      如果看不明白什么是信息增益(information gain)和熵(entropy) , 请不要着急----它们自诞生的那一天起,就注定会令世人十分费解。克劳德•香农写完信息论之后,约翰•冯• 诺依曼建议使用“熵”这个术语,因为大家都不知道它是什么意思。

        其中n是分类的数目
       下面我们将学习如何使用python计算信息熵,创建名为tree.py的文件,将程序清单3-1的代码内容录人到tree.py文件中,此代码的功能是计算给定数据集的熵。


 

3.1.2 划分数据集


 

3.1.3 递归构建决策树

     程序清单3-4的代码使用两个输人参数:数据集和标签列表。标签列表包含了数据集中所有特征的标签,算法本身并不需要这个变量,但是为了给出数据明确的含义,我们将它作为一个输人参数提供。此外,前面提到的对数据集的要求这里依然需要满足。上述代码首先创建了名为classList化的列表变量,其中包含了数据集的所有类标签。递归函数的第一个停止条件是所有的类标签完全相同,则直接返回该类标签0 。递归函数的第二个停止条件是使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。由于第二个条件无法简单地返回唯一的类标签,这里使用程序清单3-3的函数挑选出现次数最多的类别作为返回值。

      下一步程序开始创建树,这里使用python语言的字典类型存储树的信息,当然也可以声明特殊的数据类型存储树,但是这里完全没有必要。字典变量mytree存储了树的所有信息,这对于其后绘制树形图非常重要。当前数据集选取的最好特征存储在变量beStFeat 中,得到列表包含的所有属性值。这部分代码与程序清单3-3中的部分代码类似,这里就不再进一步解释了。

       最后代码遍历当前选择特征包含的所有属性值,在每个数据集划分上递归调用函数createTree ( ) ,得到的返回值将被插人到字典变量mytree 中,因此函数终止执行时,宇典中将会嵌套很多代表叶子节点信息的字典数据。在解释这个嵌套数据之前,我们先看一下循环的第一行subLabels = labels[:],这行代码复制了类标签,并将其存储在新列表变量即证让訂沖。之所以这样做,是因为在python吾言中函数参数是列表类型时,参数是按照引用方式传递的。为了保证每次调用函数createTree ( )时不改变原始列表的内容,使用新变量subLabels代替原始列表。


 

3.2 在Python中使用Matplotlib注解绘制树形图

3.2.1 Matplotlib 注解

        本书将使用Matpl0tlib的注解功能绘制树形图,它可以对文字着色并提供多种形状以供选择,而且我们还可以反转箭头,将它指向文本框而不是数据点。打开文本编辑器,创建名为treePlotter.py的新文件,然后输人下面的程序代码。


 

3.2.2 构造注解树

 


 

3.3 测试和存储分类器

3.3.1 测试算法:使用决策树执行分类


 

3.3.2 使用算法:决策树的存储


 

3.4 示例:使用决策树预测隐形眼镜类型


 

3.5 本章小结

 

posted on 2016-05-01 11:19  飞鸟各投林  阅读(610)  评论(0编辑  收藏  举报