决策树(decision tree)

news2024/12/24 11:18:41

决策树构建:特征选择、决策树的生成和决策树的修剪。

特征选择

特征选择在于选取对训练数据具有分类能力的特征。这样可以提高决策树学习的效率,如果利用一个特征进行分类的结果与随机分类的结果没有很大差别,则称这个特征是没有分类能力的。经验上扔掉这样的特征对决策树学习的精度影响不大。通常特征选择的标准是信息增益(information gain)或信息增益比.

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

熵定义为信息的期望值。在信息论与概率统计中,熵是表示随机变量不确定性的度量

from math import log

"""
函数说明:创建测试数据集

Parameters:
    无
Returns:
    dataSet - 数据集
    labels - 分类属性
"""

def createDataSet():
    dataSet = [[0, 0, 0, 0, 'no'],  # 数据集
               [0, 0, 0, 1, 'no'],
               [0, 1, 0, 1, 'yes'],
               [0, 1, 1, 0, 'yes'],
               [0, 0, 0, 0, 'no'],
               [1, 0, 0, 0, 'no'],
               [1, 0, 0, 1, 'no'],
               [1, 1, 1, 1, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [2, 0, 1, 2, 'yes'],
               [2, 0, 1, 1, 'yes'],
               [2, 1, 0, 1, 'yes'],
               [2, 1, 0, 2, 'yes'],
               [2, 0, 0, 0, 'no']]
    labels = ['不放贷', '放贷']  # 分类属性
    return dataSet, labels  # 返回数据集和分类属性

"""
函数说明:计算给定数据集的经验熵(香农熵)
Parameters:
    dataSet - 数据集
Returns:
    shannonEnt - 经验熵(香农熵)
"""

def calcShannonEnt(dataSet):
    numEntires = len(dataSet)  # 返回数据集的行数
    labelCounts = {}  # 保存每个标签(Label)出现次数的字典
    for featVec in dataSet:  # 对每组特征向量进行统计
        currentLabel = featVec[-1]  # 提取标签(Label)信息
        if currentLabel not in labelCounts.keys():  # 如果标签(Label)没有放入统计次数的字典,添加进去
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1  # Label计数
    shannonEnt = 0.0  # 经验熵(香农熵)
    for key in labelCounts:  # 计算香农熵
        prob = float(labelCounts[key]) / numEntires  # 选择该标签(Label)的概率
        shannonEnt -= prob * log(prob, 2)  # 利用公式计算
    return shannonEnt  # 返回经验熵(香农熵)

if __name__ == '__main__':
    dataSet, features = createDataSet()
    print(dataSet)
    print(calcShannonEnt(dataSet))

信息增益

信息增益是相对于特征而言的,信息增益越大,特征对最终的分类结果影响也就越大。

条件熵

条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性,随机变量X给定的条件下随机变量Y的条件熵(conditional entropy)H(Y|X),定义为X给定条件下Y的条件概率分布的熵对X的数学期望:

 信息增益

特征A对训练数据集D的信息增益g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差:

一般地,熵H(D)与条件熵H(D|A)之差称为互信息(mutual information)。决策树学习中的信息增益等价于训练数据集中类与特征的互信息。

from math import log

"""
函数说明:计算给定数据集的经验熵(香农熵)

Parameters:
    dataSet - 数据集
Returns:
    shannonEnt - 经验熵(香农熵)
"""

def calcShannonEnt(dataSet):
    numEntires = len(dataSet)  # 返回数据集的行数
    labelCounts = {}  # 保存每个标签(Label)出现次数的字典
    for featVec in dataSet:  # 对每组特征向量进行统计
        currentLabel = featVec[-1]  # 提取标签(Label)信息
        if currentLabel not in labelCounts.keys():  # 如果标签(Label)没有放入统计次数的字典,添加进去
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1  # Label计数
    shannonEnt = 0.0  # 经验熵(香农熵)
    for key in labelCounts:  # 计算香农熵
        prob = float(labelCounts[key]) / numEntires  # 选择该标签(Label)的概率
        shannonEnt -= prob * log(prob, 2)  # 利用公式计算
    return shannonEnt  # 返回经验熵(香农熵)

"""
函数说明:创建测试数据集

Parameters:
    无
Returns:
    dataSet - 数据集
    labels - 分类属性
"""

def createDataSet():
    dataSet = [[0, 0, 0, 0, 'no'],  # 数据集
               [0, 0, 0, 1, 'no'],
               [0, 1, 0, 1, 'yes'],
               [0, 1, 1, 0, 'yes'],
               [0, 0, 0, 0, 'no'],
               [1, 0, 0, 0, 'no'],
               [1, 0, 0, 1, 'no'],
               [1, 1, 1, 1, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [2, 0, 1, 2, 'yes'],
               [2, 0, 1, 1, 'yes'],
               [2, 1, 0, 1, 'yes'],
               [2, 1, 0, 2, 'yes'],
               [2, 0, 0, 0, 'no']]
    labels = ['不放贷', '放贷']  # 分类属性
    return dataSet, labels  # 返回数据集和分类属性

"""
函数说明:按照给定特征划分数据集

Parameters:
    dataSet - 待划分的数据集
    axis - 划分数据集的特征
    value - 需要返回的特征的值
"""


def splitDataSet(dataSet, axis, value):
    retDataSet = []  # 创建返回的数据集列表
    for featVec in dataSet:  # 遍历数据集
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]  # 去掉axis特征
            reducedFeatVec.extend(featVec[axis + 1:])  # 将符合条件的添加到返回的数据集
            retDataSet.append(reducedFeatVec)
    return retDataSet  # 返回划分后的数据集

"""
函数说明:选择最优特征

Parameters:
    dataSet - 数据集
Returns:
    bestFeature - 信息增益最大的(最优)特征的索引值
"""

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1  # 特征数量
    baseEntropy = calcShannonEnt(dataSet)  # 计算数据集的香农熵
    bestInfoGain = 0.0  # 信息增益
    bestFeature = -1  # 最优特征的索引值
    for i in range(numFeatures):  # 遍历所有特征
        # 获取dataSet的第i个所有特征
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)  # 创建set集合{},元素不可重复
        newEntropy = 0.0  # 经验条件熵
        for value in uniqueVals:  # 计算信息增益
            subDataSet = splitDataSet(dataSet, i, value)  # subDataSet划分后的子集
            prob = len(subDataSet) / float(len(dataSet))  # 计算子集的概率
            newEntropy += prob * calcShannonEnt(subDataSet)  # 根据公式计算经验条件熵
        infoGain = baseEntropy - newEntropy  # 信息增益
        print("第%d个特征的增益为%.3f" % (i, infoGain))  # 打印每个特征的信息增益
        if (infoGain > bestInfoGain):  # 计算信息增益
            bestInfoGain = infoGain  # 更新信息增益,找到最大的信息增益
            bestFeature = i  # 记录信息增益最大的特征的索引值
    return bestFeature  # 返回信息增益最大的特征的索引值

if __name__ == '__main__':
    dataSet, features = createDataSet()
    print("最优特征索引值:" + str(chooseBestFeatureToSplit(dataSet)))

决策树构建

ID3算法

ID3算法的核心是在决策树各个结点上对应信息增益准则选择特征,递归地构建决策树。具体方法是:从根结点(root node)开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子节点;再对子结点递归地调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止

from math import log
import operator

"""
函数说明:计算给定数据集的经验熵(香农熵)

Parameters:
    dataSet - 数据集
Returns:
    shannonEnt - 经验熵(香农熵)
"""

def calcShannonEnt(dataSet):
    numEntires = len(dataSet)  # 返回数据集的行数
    labelCounts = {}  # 保存每个标签(Label)出现次数的字典
    for featVec in dataSet:  # 对每组特征向量进行统计
        currentLabel = featVec[-1]  # 提取标签(Label)信息
        if currentLabel not in labelCounts.keys():  # 如果标签(Label)没有放入统计次数的字典,添加进去
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1  # Label计数
    shannonEnt = 0.0  # 经验熵(香农熵)
    for key in labelCounts:  # 计算香农熵
        prob = float(labelCounts[key]) / numEntires  # 选择该标签(Label)的概率
        shannonEnt -= prob * log(prob, 2)  # 利用公式计算
    return shannonEnt  # 返回经验熵(香农熵)


"""
函数说明:创建测试数据集

Parameters:
    无
Returns:
    dataSet - 数据集
    labels - 特征标签
"""


def createDataSet():
    dataSet = [[0, 0, 0, 0, 'no'],  # 数据集
               [0, 0, 0, 1, 'no'],
               [0, 1, 0, 1, 'yes'],
               [0, 1, 1, 0, 'yes'],
               [0, 0, 0, 0, 'no'],
               [1, 0, 0, 0, 'no'],
               [1, 0, 0, 1, 'no'],
               [1, 1, 1, 1, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [1, 0, 1, 2, 'yes'],
               [2, 0, 1, 2, 'yes'],
               [2, 0, 1, 1, 'yes'],
               [2, 1, 0, 1, 'yes'],
               [2, 1, 0, 2, 'yes'],
               [2, 0, 0, 0, 'no']]
    labels = ['年龄', '有工作', '有自己的房子', '信贷情况']  # 特征标签
    return dataSet, labels  # 返回数据集和分类属性


"""
函数说明:按照给定特征划分数据集

Parameters:
    dataSet - 待划分的数据集
    axis - 划分数据集的特征
    value - 需要返回的特征的值
Returns:
    无
"""


def splitDataSet(dataSet, axis, value):
    retDataSet = []  # 创建返回的数据集列表
    for featVec in dataSet:  # 遍历数据集
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]  # 去掉axis特征
            reducedFeatVec.extend(featVec[axis + 1:])  # 将符合条件的添加到返回的数据集
            retDataSet.append(reducedFeatVec)
    return retDataSet  # 返回划分后的数据集

"""
函数说明:选择最优特征

Parameters:
    dataSet - 数据集
Returns:
    bestFeature - 信息增益最大的(最优)特征的索引值
"""

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1  # 特征数量
    baseEntropy = calcShannonEnt(dataSet)  # 计算数据集的香农熵
    bestInfoGain = 0.0  # 信息增益
    bestFeature = -1  # 最优特征的索引值
    for i in range(numFeatures):  # 遍历所有特征
        # 获取dataSet的第i个所有特征
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)  # 创建set集合{},元素不可重复
        newEntropy = 0.0  # 经验条件熵
        for value in uniqueVals:  # 计算信息增益
            subDataSet = splitDataSet(dataSet, i, value)  # subDataSet划分后的子集
            prob = len(subDataSet) / float(len(dataSet))  # 计算子集的概率
            newEntropy += prob * calcShannonEnt(subDataSet)  # 根据公式计算经验条件熵
        infoGain = baseEntropy - newEntropy  # 信息增益
        # print("第%d个特征的增益为%.3f" % (i, infoGain))            #打印每个特征的信息增益
        if (infoGain > bestInfoGain):  # 计算信息增益
            bestInfoGain = infoGain  # 更新信息增益,找到最大的信息增益
            bestFeature = i  # 记录信息增益最大的特征的索引值
    return bestFeature  # 返回信息增益最大的特征的索引值

"""
函数说明:统计classList中出现此处最多的元素(类标签)

Parameters:
    classList - 类标签列表
Returns:
    sortedClassCount[0][0] - 出现此处最多的元素(类标签)
"""

def majorityCnt(classList):
    classCount = {}
    for vote in classList:  # 统计classList中每个元素出现的次数
        if vote not in classCount.keys(): classCount[vote] = 0
        classCount[vote] += 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)  # 根据字典的值降序排序
    return sortedClassCount[0][0]  # 返回classList中出现次数最多的元素

"""
函数说明:创建决策树

Parameters:
    dataSet - 训练数据集
    labels - 分类属性标签
    featLabels - 存储选择的最优特征标签
Returns:
    myTree - 决策树
"""

def createTree(dataSet, labels, featLabels):
    classList = [example[-1] for example in dataSet]  # 取分类标签(是否放贷:yes or no)
    if classList.count(classList[0]) == len(classList):  # 如果类别完全相同则停止继续划分
        return classList[0]
    if len(dataSet[0]) == 1 or len(labels) == 0:  # 遍历完所有特征时返回出现次数最多的类标签
        return majorityCnt(classList)
    bestFeat = chooseBestFeatureToSplit(dataSet)  # 选择最优特征
    bestFeatLabel = labels[bestFeat]  # 最优特征的标签
    featLabels.append(bestFeatLabel)
    myTree = {bestFeatLabel: {}}  # 根据最优特征的标签生成树
    del (labels[bestFeat])  # 删除已经使用特征标签
    featValues = [example[bestFeat] for example in dataSet]  # 得到训练集中所有最优特征的属性值
    uniqueVals = set(featValues)  # 去掉重复的属性值
    for value in uniqueVals:  # 遍历特征,创建决策树。
        subLabels = labels[:]
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels, featLabels)
    return myTree

if __name__ == '__main__':
    dataSet, labels = createDataSet()
    featLabels = []
    myTree = createTree(dataSet, labels, featLabels)
    print(myTree)

参考文献

机器学习实战教程(二):决策树基础篇之让我们从相亲说起 (cuijiahua.com)

机器学习实战教程(三):决策树实战篇之为自己配个隐形眼镜 (cuijiahua.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/75973.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Lifeform——站在3D虚拟数字身份与元宇宙结合的风口之上

Web3和元宇宙是公认的下一个风口,吸引了大量用户的关注和参与。从《我的世界》中的场景编辑器,到DecentreLand,以及Sandbox中玩家对自己虚拟地块的装饰。人们在虚拟世界中举办各种活动,比如演唱会、节日庆祝或者比赛、游戏甚至婚礼…

PrizmDoc Viewer添加了新的Excel渲染选项

PrizmDoc Viewer添加了新的Excel渲染选项 添加了新的Microsoft Excel渲染选项。PrizmDoc Viewer现在提供了在MSO渲染模式下查看Excel文档时自动调整单元格宽度和/或高度的选项。 PrizmDoc Viewer Microsoft Office转换附加选项现在与运行在Microsoft Windows Server 2019/2022上…

谷粒商城8:分布式锁使用和springcache的整合

1.分布式锁redisson使用 ①分布式锁简介 ②分布式锁学习过程 ③最终分析 加入锁为原子操作:设置过期时间设置锁 删除锁为原子操作:业务流程删除锁 将锁的过期时间调长 ④Redisson的使用 引入依赖程序化配置使用 创建redisson客户端 Redisson.create(…

6.论文学习Modality-aware Mutual Learning for Multi-modal Medical Image Segmentation

目录一.摘要1.背景解决方法1.如何有效整合来自多模态医学图像的信息2.如何处理常见模式缺失的情况2.解决1.ML2.MA3.结论二.方法2.1模态特定模型Modality-specific Model2.2 Modality-Aware Module2.3互学策略Mutual Learning Strategy三.实验与结果3.1数据集和评估指标3.2运行细…

杨校老师课堂之Spring Boot框架面试题【开发工程师面试前必看】

1. 什么是 Spring Boot? Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用Spring 的难度,简省了繁重的配置,提供了各种启动器,使开发者能快速上手。 2. 为什么要用…

c#入门-别名引用

别名引用 如果你引用的命名空间中出现了同名的类,那么会无法判断你使用的类型。 当然,你可以使用完全限定名。 或者,你可以为其中一个类型指代别名。 使用引用命名空间语句,为一个标识符赋值一个类型。 可以使用这个标识符代替…

基于java+springmvc+mybatis+jsp+mysql的通信簿管理系统

项目介绍 前端页面: 功能:首页、日志信息、心情日志、相册信息、个人中心、后台管理 管理员后台页面: 功能:主页、个人中心、用户管理、日志信息管理、日志类别管理、心情日志管理、相册信息管理、系统管理 开发环境 开发语言&…

C#【必备技能篇】Marshal是什么?怎么用?

文章目录学习来源:MSDN官方文档一、Marshal是什么?1、英文释义:2、在MSDN中的定义:3、通俗理解:二、Marshal怎么用?【主要以一些实例来了解】1、Marshal下的方法_部分截图【C#源码】:2、一些示例…

自定义RBAC(3)

您好,我是湘王,这是我的CSDN博客,欢迎您来,欢迎您再来~ RBAC类型的权限,本质上是一种对资源访问路径的控制,且具有典型的树型层次结构。而树型结构,天然地就有父结点和子结点的关系以…

【HarmonyOS】ArkTS Native开发——使用 system函数创建文件

ArkTS是HamronyOS优选的主力语言,但官方文档指南中对于Native应用开发并没有详细的描述,只有一篇Codelab可以学习(简易Native C 示例(ArkTS) (huawei.com)),本文将在Native应用中使用C/C的syste…

计算机毕业设计ssm+vue基本微信小程序的早茶预定系统 uniapp 小程序

项目介绍 本文介绍了使用微信小程序技术开发早茶预定系统的设计与实现过程,首先对实现该系统的技术进行分析,说明选择Java后台技术和MySQL数据库的必要性,然后对基于微信小程序的早茶预定系统的需求进行分析。并接着对系统进行设计,包括架构设计、功能设计、数据库设计。最后进…

关于商业智能 BI 认知上的误区,你有几个

关于商业智能BI的介绍,网络上有太多的杂音,总而言之会把商业智能BI讲解的貌似很简单,感觉上买了一个工具就可以解决所有的问题,这其实是一个非常大的误区。 商业智能BI - 派可数据商业智能BI可视化分析平台 我这里总结了一下&…

宠物店微信小程序开发步骤_宠物店管理系统用什么做

大多数人对于动物医疗专业知识比较匮乏,再加上宠物医疗费用,日常用品都略高,宠物店/宠物医院的前景,再未来依旧可观。 相比于实体店,线上平台无疑有着更广阔的拓客渠道和销售前景,做宠物店/宠物医院小程序…

如何高效制作数据可视化大屏,大屏高效制作攻略分享,总有一款适合你

做数据可视化大屏可不是一件简单的事情,里面有很多技巧,像布局,配色,图表和素材的选用和搭配等等,里面有很多学问。一时半会也做不出一个大屏,即使你会做也需要一定的时间和精力,在大量的需求下…

ABAP学习笔记之——第十一章:Function ALV

一、Function ALV Function ALV 从名字中可以推出,是由 Function(函数)形式提供,因此开发者只需适当使用以有的功能即可。没有必要创建屏幕也没有必要一一写出代码,因此可认为是生产性比较高的方法。 例: *function ALV GRID和…

【测绘程序设计】——大地坐标与空间直角坐标转换

本文分享了 测绘程序设计——大地坐标(B,L,H)与空间直角坐标(X,Y,Z)转换(C#版与Python版),相关源代码(绝对完整,直接运行)与使用示例如下。 目录 Part.Ⅰ 使用示例Chap.Ⅰ C#版Chap.Ⅱ Python版Part.Ⅱ 代码分析Chap.Ⅰ C#版Chap.Ⅱ Python版Part.Ⅲ 源码下载Part.Ⅰ…

12.9 总结

一.复制带有随机指针的链表 要求结构和val都是一样 这个题目我们可以建立一个map表,把新的链表和旧的链表每个节点都构成一组key-val对应 然后遍历旧链表.找到对应的next值和random值 思路: 方法1:迭代map class Solution { public Node copyRandomList(Node head) { if(hea…

Mysql 8.0.31彻底卸载

我们有时需要将mysql卸载重新安装,然而如果不注意其中的细节,只是使用apt remove mysql-server命令是卸载不干净的,即使使用了apt purge mysql-server命令进行卸载再重新安装的mysql还是会保留着原来的密码。正确的操作方式是下面这样子的。 …

百度智能云发布基于Ampere® Altra®的高能效云服务器GR1实例

2021年,百度公布了2030年碳中和目标以及6条科学实现路径。首要举措便是建设更环保的数据中心。百度自建的数据中心PUE一直处于非常领先的位置。百度一直秉持“科技为更好”的可持续发展理念,依托全栈和领先的人工智能技术和丰富的产业实践,在…

前端项目工程化流程(简陋版)

背景 最近想要自己做开始一个项目,然后发现好像挺久没有出 从 0 开始 一个项目了,对项目的一些工程化方面的流程有点生疏了,感觉就是知道一个大概的流程,很多都要靠搜索引擎来帮忙,我就想整理一下,对于前端…