机器学习实战第三章

决策树

  • 说明:本章节所有代码使用版本为Python3

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

解释:
  标称型:标称型目标变量的结果只在有限目标集中取值,比如真与假(标称型目标变量主要用于分类)
  数值型(连续型):数值型目标变量则可以从无限的数值集合中取值

  决策树经常用于解决处理分类问题,它的一个重要任务是为了理解数据中所蕴含的知识信息,因此决策树可以使用不熟悉的数据集并从中提取出一系列规则,这些机器根据数据集创建规则的过程,就是机器学习的过程。专家系统中经常使用决策树,而且决策树给出结果往往可以匹敌人类专家。

决策树的构造

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

一些决策树算法采用二分法划分数据,而这里使用ID3算法划分数据集,每一次划分数据集时只选取一个特征属性。

1、信息增益

  划分数据集的最大原则:将无序的数据变得有序。组织杂乱无章数据的一种方式就是使用信息论度量信息,量信息是量化处理信息的分支科学。我们可以在划分数据之前或之后使用信息量化度量信息的内容。
  划分数据之前之后信息发生的变化称之为信息增益,知道如何计算信息增益,就可以计算每一个特征值划分数据集获得信息增益,获得信息增益最高的特征就是最好的选择。
  集合信息的度量方式是香农熵或简称熵。熵定义信息的期望值。若待分类的事务可能划分在多个分类之中,则符号x_i的信息定义为:

l ( x i ) = − l o g 2 p ( x i ) l(x_i)=-log_2 p(x_i) l(xi)=log2p(xi)

  为了计算熵,需要计算所有类别所有可能包含的信息期望,通过下面公式得到:

− ∑ i = 1 n p ( x i ) l o g 2 p ( x i ) -\sum_{i=1}^n p(x_i) log_2 p(x_i) i=1np(xi)log2p(xi)

  熵越高,混合的数据也就越多。得到熵之后,可以按照获取最大信息增益的方法划分数据集。

2、划分数据集

  分类算法除了需要测量信息熵,还需要划分数据集,度量划分数据的熵,以便判断当前是否正确的划分了数据集。我们对每一个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最好的方式。

3、递归构建决策树

  目前我们已经学习了冲数据集构造决策树所需的子功能模块。其工作原理是:

  1. 得到原始数据集
  2. 基于最好的属性值划分数据集,由于特征值可能有多于两个,因此可能存在大于两个分支的数据划分
  3. 第一次划分后,数据将向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据集
  4. 最后采用递归的原则处理数据集

  递归结束的条件是:遍历完所有的数据集的属性,或者每个分支下的所有实例都具有相同的分类。若所有实例都具有相同的分类,则得到一个叶子节点或者终止块。任何到达叶子节点的数据必然是属于叶子节点的分类。

from math import log
import operator

# 自己创建简单的数据集
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

# 计算给定数据集的香农熵
def calcShannonEnt(dataSet):
    numEntries = len(dataSet)
    # 获取传来数据集的长度
    labelCounts = {
   }
    for featVec in dataSet:
        currentLabel = featVec[-1]
        # 获取数据每一行数据集的最后一个元素
        if currentLabel not in labelCounts.keys():
            labelCounts[currentLabel] = 0
        # 如果最后一个数据的元素不在labelCounts集合中,则添加进去,值为0
        labelCounts[currentLabel] += 1
        # for循环中是为所有的可能分类创造字典
    shannonEnt = 0.0
    for key in labelCounts:
        prob = float(labelCounts[key])/numEntries
        # labelCounts[key]表示字典中key所对应的value值
        # prob计算出,每一个key所出现的概率
        shannonEnt -= prob*log(prob, 2)
        # 以2为底求对数,根据计算香农熵的公式得出的
    return shannonEnt

# 给定特征划分数据集
def splitDataSet(dataSet, axis, value):
    # dataSet表示待划分的数据集,axis表示划分数据集的特征,value表示需要返回的特征值
    retDataSet = []
    # 创建list对象
    for featVec in dataSet:
        if featVec[axis] == value:
            # 将符合特征的数据抽取出来
            reducedFeatVec = featVec[:axis]
            # 指定特征之前的数据
            reducedFeatVec.extend(featVec[axis+1:])
            # 指定特征之后的数据,extend在已存在的列表中添加新的列表内容
            retDataSet.append(reducedFeatVec)
            # retDataSet相比于reducedFeatVec没有了特征数据
            # 注意extend与append的区别,extend是将每一个元素分别合并到列表中,而append是将一个列表当作一个元素合并到列表中
    return retDataSet
    # 返回符合要求的元素


# 选择最好的数据划分方式
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0])-1
    # #统计特征数目(最后一个元素不是特征所以要删去)
    baseEntropy = calcShannonEnt(dataSet)
    # 计算原始数据的香农熵
    bestInfoGain = 
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值