机器学习—决策树(ID3)

本文详细介绍了决策树算法,包括ID3算法的相关知识,如何构造决策树,选择最佳特征的方法,以及使用Python实现决策树的步骤。通过实例展示了计算香农熵、划分数据集、构建决策树、存储和绘制决策树的过程,并应用于预测隐形眼镜类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、相关知识

1 决策树算法

     在构造决策树时,第一个需要解决的问题就是,如何确定出哪个特征在划分数据分类是起决定性作用,或者说使用哪个特征分类能实现最好的分类效果。这样,为了找到决定性的特征,划分川最好的结果,我们就需要评估每个特征。当找到最优特征后,依此特征,数据集就被划分为几个数据子集,这些数据自己会分布在该决策点的所有分支中。此时,如果某个分支下的数据属于同一类型,则该分支下的数据分类已经完成,无需进行下一步的数据集分类;如果分支下的数据子集内数据不属于同一类型,那么就要重复划分该数据集的过程,按照划分原始数据集相同的原则,确定出该数据子集中的最优特征,继续对数据子集进行分类,直到所有的特征已经遍历完成,或者所有叶结点分支下的数据具有相同的分类。
     创建分支的伪代码函数createBranch()如下:

     检测数据集中的每一个子项是否属于同一分类: 

if so return 类标签;
else
      寻找划分数据集的最好特征
      划分数据集
      创建分支结点
            for 每个分支结点
                 调用函数createBranch并增加返回结点到分支结点中//递归调用createBranch()
      return 分支结点

    了解了如何划分数据集后,我们可以总结出决策树的一般流程:
    (1)收集数据:可以使用任何方法
    (2)准备数据:构造树算法只适用于标称型数据,因此数值型数据必须离散化
    (3)分析数据:可以使用任何方法,构造树完成之后,应该检查图形是否符合预期
    (4)训练数据:上述的构造树过程构造决策树的数据结构
    (5)测试算法:使用经验树计算错误率
    (6)使用算法:在实际中更好地理解数据内在含义

2 最好特征选取的规则:信息增益

     划分数据集的大原则是:将无序的数据变得更加有序。在划分数据集前后信息发生的变化称为信息增益,如果我们知道如何计算信息增益,就可以计算每个特征值划分数据集获得的信息增益,而获取信息增益最高的特征就是最好的特征。
     接下来,我们讲学习如何计算信息增益,而提到信息增益我们又不得不提到一个概念"香农熵",或者简称熵。熵定义为信息的期望值。
     如果待分类的事物可能会出现多个结果x,则第i个结果xi发生的概率为p(xi),那么我们可以由此计算出xi的信息熵为l(xi)=p(xi)log(1/p(xi))=-p(xi)log(p(xi))
那么,对于所有可能出现的结果,事物所包含的信息希望值(信息熵)就为:H=-Σp(xi)log(p(xi)),i属于所有可能的结果
     这样,假设利用数据集中某一特征A对数据集D(D的分类类别有n种)进行分类,而特征A取值有k种,那么此时,利用特征A对数据集进行分类的信息增益为:
     信息增益H(D,A)=原始数据集的信息熵H(D)-特征A对数据集进行划分后信息熵H(D/A)
其中H(D/A)=∑|Aj|/|D|*H(Aj),j属于A的k种取值,|Aj|和|D|分别表示,特征A第j种取值的样本数占所有取值样本总数的比例,以及数据集的样本总数

二、构造决策树

      创建名为trees.py的文件将代码全部写到该文件中。

1 计算给定数据集的香农熵

# 计算给定数据集的熵
def clacShannonEnt(dataSet):
    # 获取数据集的行数
    numEntries = len(dataSet)
    # 设置字典数据结构
    labelCounts = {}
    # 提取数据集的每一行的特征向量
    for featVec in dataSet:
        # 获取特征向量的最后一列的标签
        currentLabel = featVec[-1]
        # 检测字典的关键字key中是否存在该标签 如果不存在keys()关键字
        if currentLabel not in labelCounts.keys():
            # 将当前标签/0键值对存入字典中
            labelCounts[currentLabel] = 0
        # 否则将当前标签对应的键值加1
        labelCounts[currentLabel] += 1
    # 初始化熵为0
    shannonEnt = 0.0
    # 对于数据集中所有的分类类别
    for key in labelCounts:
        # 计算各个类别出现的频率
        prob = float(labelCounts[key])/numEntries
        # 计算各个类别信息期望值
        shannonEnt -= prob * log(prob,2)
    return shannonEnt

2 用createDataSet函数创建自己需要的数据集

# 创建自己定义的数据集
def createDataSet():
    dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,0,'no']]
    labels = ['no surfacing','flippers']
    return dataSet,labels

        在Python命令提示符下输入下列命令,计算该数据集的香农熵(需要说明的是,熵越高,那么混合的数据就越多,如果我们在数据集中添加更多的分类,会导致熵结果增大):

>>> import trees
>>> myData,labels = trees.createDataSet()
>>> myData
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 0, 'no']]
>>> labels
['no surfacing', 'flippers']
>>> trees.clacShannonEnt(myData)
0.9709505944546686

3 划分数据集

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

#划分数据集:按照最优特征划分数据集 #@dataSet:待划分的数据集 #@axis:划分数据集的特征 #@value:特征的取值
def splitDataSet(dataSet,axis,value):
    # 需要说明的是,python语言传递参数列表时,传递的是列表的引用 # 如果在函数内部对列表对象进行修改,将会导致列表发生变化,为了不修改原始数据集,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值