《机器学习实战笔记--第一部分 分类算法:决策树 1》

    决策树是最经常使用的数据挖掘算法,他之所以如此流行,一个很重要的原因是使用者基本不用了解机器学习算法,也不用深究他是如何工作的。


3-1就是一个决策树,正方形表示判断模块,椭圆形表示终止模块,从模块引出的箭头称作分支,他可以到达另一个判断模块或则终止模块。我们之前介绍的KNN最大的缺点就是无法得出数据的内在意义,而决策树的主要优势就是在于数据形式非常容易理解。

    下面我们将构造决策树算法,能够读取数据集合,构造类似于上图的决策树,决策树很多任务都是为了数据中所蕴含的知识信息,因此决策树可以使用不熟悉的数据集合,并从中提取一系列规则,机器学习算法最终将使用这些机器从数据集中创造的规则。专家系统常用决策树,而且决策树给出的结果往往很不错。

    接下来我们将学习从一堆原始数据中构造决策树。首先我们将讨论构造决策树的方法,以及如何编写构造树的python代码,然后学习一些度量算法成功率的方法,最后使用递归分类器,并使用matplotlib绘制决策树图。构造完成决策树之后,我们将输入一些数据,并由决策树来决出结果。

    1、决策树的构造


    首先我们将在数学上讨论使用信息论来划分数据集,然后编写代码将理论应用到具体的数据集上,最后编写代码构建决策树。

    第一个问题,我们要知道当前数据集上哪个特征在分类数据时起到决定性作用。为了找到决定性的特征,划分出最好的结果,我们必须评估每个特征。完成测试之后,原始数据就被划分为几个数据子集。这些数据子集会分布在第一个决策点的所有分支上。如果某个分支下面的数据都属于同一种类型,那么就不需要再对数据进行划分了。如果数据子集内的数据不是同一类型的,就需要重复划分子集。划分子集的方法和划分原始书记的方法相同,直到所有具有相同类型的数据全在一个子集内。

    伪代码如下:

If so return 类标签;

Else

    寻找划分数据集的最好特征

    划分数据集

    创建分支点

        for 每个划分的子集

            调用函数,并增加返回结果到分支节点中去

    return 分支节点



    我们使用ID3算法划分数据集,该算法用来处理如何划分数据集,何时停止数据集,每次划分我们只选用一个特征属性。

    我们必须采用量化的方法来划分这些数据:

    信息增益

    划分数据集的最大原则是:将无序的数据变得更加有序。我们可以使用多种方法划分数据集,但是每种方法都有各自的优缺点。

    在划分数据集之前之后发生的变化成为信息增益,知道如何计算信息增益,我们就可以计算每个特征划分数据集获得的增益,所得信息增益最高的特征就是最好的选择。

    集合信息的度量方式称为香浓熵或则熵。


    

           

   下面是计算信息熵的python程序:计算给定数据集的熵

from math import log

def calcShannonEnt(dataSet):
    #数据的实例总数
    numEntries = len(dataSet)
    #创建一个数据字典,它的键值是最后一列的数值
    labelCounts = {}
    for featVec in dataSet:
        currentLabel = featVec[-1]
        #如果当前键值不存在,则将当前键值加入字典。每个键值都记录了当前类别出现的次数
        if currentLabel not in labelCounts.keys():
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1
    shannonEnt =0.0
    for key in labelCounts:
        prob = float(labelCounts[key])/numEntries
        shannonEnt -= prob * log(prob,2)
    return shannonEnt 

    再利用createDataSet()函数得到鉴定数据集:

def createDataSet():
    dataSet = [[1,1,'yes'],
               [1,1,'yes'],
               [1,0,'no'],
               [0,1,'no'],
               [0,1,'no']]
    labels = ['no surfacing', 'flippers']

    return dataSet, labels

我们可以得到运算的结果:


    熵越高则混合的数据也就越多,我们可以在数据集中添加更多的分类,观察熵是如何变化的。

这里我们增加第三个名为maybe的分类,测试熵的变化:


计算熵之后,我们就可以按照最大信息增益的方法来划分数据集。


    划分数据集:

    除了计算信息熵,还要进行划分数据集,度量划分数据集的熵,以便判断当前是否正确的划分了数据集。我们将对每个特征划分数据集的结果计算一次信息熵,以便判断哪个特征是划分数据最好的。

 按照给定特征划分数据集的程序:

    

我们可以得到这样的划分结果。

接下来我们会遍历整个数据集,循环计算香浓熵和splitDataSet()函数,找到最好的特征划分方式。

程序:选择最好的数据集划分方式:

def chooseBestFeatureToSplit(dataSet):
    '''
    数据满足的要求:1、数据必须是一种由列表元素组成的列表,且所有列表元素相同
                    2、数据的最后一列必须是当前实例的类别标签
    '''
    numFeatures = len(dataSet[0]) - 1
    #计算数据集的香浓熵,用于与划分后的香浓熵进行比较
    baseEntropy = calcShannonEnt(dataSet)
    bestInfoGain = 0.0
    bestFeature = -1
    '''
    取出每一个特征的所有特征值,所有的特征值都被取出
    然后按照每个特征值进行分类
    计算分类后的信息熵
    '''
    for i in range(numFeatures):
        '''
        基本格式
  列表推导式:
  variable = [out_exp_res for out_exp in input_list if out_exp == 2]
  out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
  for out_exp in input_list:  迭代input_list将out_exp传入out_exp_res表达式中。
  if out_exp == 2:  根据条件过滤哪些值可以。
        '''
        #遍历数据集中的所有特征
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        newEntropy = 0.0
        for value in uniqueVals:
            #取出第i个特征为value的所有数据
            subDataSet = splitDataSet(dataSet, i, value)
            
            prob = len(subDataSet)/float(len(dataSet))
            #周志华《机器学习》P75 4.2公式 计算信息增益
            newEntropy += prob*calcShannonEnt(subDataSet)
        infoGain = baseEntropy - newEntropy
        if(infoGain > bestInfoGain):
            bestInfoGain = infoGain
            bestFeature = i
            
    return bestFeature
    将我们之前的数据集放入其中,得到结果:

    

    也就是说我们按照第一类特征对数据集进行分类最好。我们可以看到,如果按照第一类特征进行分类,那么第一类为1的有两个‘yes’,一个‘no’,第二类为0的有两个‘no’。相比较另外两类特征的分类方法是比较好的一种分类。

猜你喜欢

转载自blog.csdn.net/qq_41635352/article/details/79989215