机器学习实战-----决策树

决策树的优点:
计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
缺点:
可能会产生过度匹配问题。
适用数据类型:
数值型和标称型。
决策树的简单工作原理:
在这里插入图片描述
在构造决策树时,我们需要解决的第一个问题是,当前数据集上哪个特征在划分数据分类时起决定性作用。为了找到决定性的特征,划分出最好的结果,我们必须评估每个特征。完成测试之后,原始数据集就被划分为几个数据子集。这些数据子集会分布在第一个决策点的所有分支上。如果某个分支下的数据属于同一类型,则当前无需阅读的垃圾邮件已经正确地划分数据分类,无需进一步对数据集进行分割。如果数据子集内的数据不属于同一类型,则需要重复划分数据子集的过程。如何划分数据子集的算法和划分原始数据集的方法相同,直到所有具有相同类型的数据均在一个数据子集内。

创建分支的伪代码函数createBranch():

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

决策树的一般流程

(1)收集数据:可以使用任何方法。
(2)准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。
(3)分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
(4)训练算法:构造树的数据结构。
(5)测试算法:使用经验树计算错误率。
(6)使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。

此处我们使用ID3算法划分数据集,该算法处理如何划分数据集,何时停止划分数据集。每次划分数据集时我们只选取一个特征属性,如果训练集中存在20个特征,第一次我们选择哪个特征作为划分的参考属性呢?
例如下表中的数据,包含5个海洋动物,特征包括:不浮出水面是否可以生存,以及是否有脚蹼。我们将这些动物分成两类:鱼类和非鱼类。我们现在想要决定依据第一个特征还是第二个特征划分数据,应如何采用量化的方法判断如何划分数据?

不浮出水面是否可以生存 是否有脚蹼 属于鱼类
1
2
3
4
5

采用量化的方法判断如何划分数据:
划分数据集的大原则是:将无序的数据变得更加有序。
信息增益:在划分数据集之前之后信息发生的变化称为信息增益。知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。
熵:信息的期望值。
如果待分类的事务可能划分在多个分类之中,则符号Xi的信息定义为:
在这里插入图片描述
其中P(Xi)是选择该分类的概率。
为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,通过下面公式得到:
在这里插入图片描述
其中n是分类的数目。
计算给定数据集的香农熵:

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
    #以2为底求对数
    #使用所有类标签的发送频率计算类别出现的概率,利用这个概率计算香农熵,统计所有类标签发送的次数
    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

显示结果:

import trees
myDat,labels = trees.createDataSet()
print(myDat)
print(trees.calcShannonEnt(myDat))

结果:

D:\exercise\机器学习实战\Scripts\python.exe D:\exercise\pythonProject\TREE\mian.py 
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
0.9709505944546686

Process finished with exit code 0

手算过程如下:
在这里插入图片描述
熵越高,则混合的数据也越多,我们可以在数据集中添加更多的分类,观察熵是如何变化的。这里我们增加第三个名为maybe的分类,测试熵的变化。
显示结果:

myDat,labels = trees.createDataSet()
print(myDat)
print(trees.calcShannonEnt(myDat))
myDat[0][-1]='maybe'
print(myDat)
print(trees.calcShannonEnt(myDat))

结果:

D:\exercise\机器学习实战\Scripts\python.exe D:\exercise\pythonProject\TREE\mian.py 
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
0.9709505944546686
[[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
1.3709505944546687

Process finished with exit code 0

手算过程如下:
在这里插入图片描述

得到熵之后,我们就可以按照获取最大信息增益的方法划分数据集。
划分数据集:
分类算法除了需要测量信息熵,还需要划分数据集,度量花费数据集的熵,以便判断当前是否正确地划分了数据集。我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最好的划分方式。
按照给定特征划分数据集:

#三个输入参数:待划分的数据集、划分数据集的特征、特征的返回值
def splitDataSet(dataSet,axis,value):
    #创建新的list对象,数据集这个列表中的各个元素也是列表,
    # 我们要遍历数据集中的每个元素,一旦发现符合要求的值,则将其添加到创建的列表中。
    retDataSet = []
    for featVec in dataSet:
        #将符合特征的数据抽取出来
        #如果featVec[axis]=value,则输出去掉axis的数组值
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

显示结果:
假定存在两个列表,a和b:
(1)

a = [1,2,3]
b = [4,5,6]
#执行a.append(b),则列表得到了第四个元素,而且第四个元素也是一个列表
a.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值