决策树算法原理+例题练习

2023-11-18

一、决策树的优缺点

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

二、一个实例

一天,老师问了个问题,只根据头发和声音怎么判断一位同学的性别。 为了解决这个问题,同学们马上简单的统计了7位同学的相关特征,数据如下:

 A同学思路,先按照头发判断,若判断不出,再按照声音判断,如下:

 由此决策树判断结果可知:头发+长声音粗是男生;头发长+声音细是女生;头发短+声音粗是男生;头发短+声音细是女生

同学B的思路,先根据声音判断,然后再根据头发判断,如下:

 此决策树的判断结果:声音细为女生,声音粗+短头发是男生;声音粗+头发长是女生。

这两个决策树,谁的更好呢?当我们有多个特征,该如何选哪个特征为最佳划分点?

三、数据集的划分原则

将无需的数据变得有序

我们可以使用多种方法划分数据集,但是每种方法都有各自的优缺点。于是我们这么想,如果我们能测量数据的复杂度,对比按不同特征分类后的数据复杂度,若按某一特征分类后复杂度减少的更多,那么这个特征即为最佳分类特征。 
Claude Shannon 定义了熵(entropy)和信息增益(information gain)。 
用熵来表示信息的复杂度,熵越大,则信息越复杂。公式如下:

信息增益(information gain),表示两个信息熵的差值。 
首先计算未分类前的熵,总共有8位同学,男生3位,女生5位。 
熵(总)=-3/8*log2(3/8)-5/8*log2(5/8)=0.9544 
接着分别计算同学A和同学B分类后信息熵。 
同学A首先按头发分类,分类后的结果为:长头发中有1男3女。短头发中有2男2女。 
熵(同学A长发)=-1/4*log2(1/4)-3/4*log2(3/4)=0.8113 
熵(同学A短发)=-2/4*log2(2/4)-2/4*log2(2/4)=1 
熵(同学A)=4/8*0.8113+4/8*1=0.9057 
信息增益(同学A)=熵(总)-熵(同学A)=0.9544-0.9057=0.0487 
同理,按同学B的方法,首先按声音特征来分,分类后的结果为:声音粗中有3男3女。声音细中有0男2女。 
熵(同学B声音粗)=-3/6*log2(3/6)-3/6*log2(3/6)=1 
熵(同学B声音粗)=-2/2*log2(2/2)=0 
熵(同学B)=6/8*1+2/8*0=0.75 
信息增益(同学B)=熵(总)-熵(同学A)=0.9544-0.75=0.2087

按同学B的方法,先按声音特征分类,信息增益更大,区分样本的能力更强,更具有代表性。 
以上就是决策树ID3算法的核心思想。 

 

from math import log
import operator

def calcShannonEnt(dataSet):  # 计算数据的熵(entropy)
    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
    for key in labelCounts:
        prob=float(labelCounts[key])/numEntries # 计算单个类的熵值
        shannonEnt-=prob*log(prob,2) # 累加每个类的熵值
    return shannonEnt

def createDataSet1():    # 创造示例数据
    dataSet = [['长', '粗', '男'],
               ['短', '粗', '男'],
               ['短', '粗', '男'],
               ['长', '细', '女'],
               ['短', '细', '女'],
               ['短', '粗', '女'],
               ['长', '粗', '女'],
               ['长', '粗', '女']]
    labels = ['头发','声音']  #两个特征
    return dataSet,labels

def splitDataSet(dataSet,axis,value): # 按某个特征分类后的数据
    retDataSet=[]
    for featVec in dataSet:
        if featVec[axis]==value:
            reducedFeatVec =featVec[:axis]
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

def chooseBestFeatureToSplit(dataSet):  # 选择最优的分类特征
    numFeatures = len(dataSet[0])-1
    baseEntropy = calcShannonEnt(dataSet)  # 原始的熵
    bestInfoGain = 0
    bestFeature = -1
    for i in range(numFeatures):
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        newEntropy = 0
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet,i,value)
            prob =len(subDataSet)/float(len(dataSet))
            newEntropy +=prob*calcShannonEnt(subDataSet)  # 按特征分类后的熵
        infoGain = baseEntropy - newEntropy  # 原始熵与按特征分类后的熵的差值
        if (infoGain>bestInfoGain):   # 若按某特征划分后,熵值减少的最大,则次特征为最优分类特征
            bestInfoGain=infoGain
            bestFeature = i
    return bestFeature

def majorityCnt(classList):    #按分类后类别数量排序,比如:最后分类为2男1女,则判定为男;
    classCount={}
    for vote in 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]

def createTree(dataSet,labels):
    classList=[example[-1] for example in dataSet]  # 类别:男或女
    if classList.count(classList[0])==len(classList):
        return classList[0]
    if len(dataSet[0])==1:
        return majorityCnt(classList)
    bestFeat=chooseBestFeatureToSplit(dataSet) #选择最优特征
    bestFeatLabel=labels[bestFeat]
    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)
    return myTree


if __name__=='__main__':
    dataSet, labels=createDataSet1()  # 创造示列数据
print(createTree(dataSet, labels))  # 输出决策树模型结果

输出结果:{'声音': {'细': '女', '粗': {'头发': {'短': '男', '长': '女'}}}}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

决策树算法原理+例题练习 的相关文章

随机推荐

  • Ubuntu安装git

    使用 apt get install git 安装git 报错 这个错误信息通常表示您的系统上没有可用的 git 软件包 这可能是因为您的软件源列表中没有包含 git 软件包所在的软件源 或者您的软件源列表已经过期 解决 如果您使用的是 U
  • RuntimeError: Attempting to deserialize object on CUDA device 1 but torch.cuda.device_count() is 1.

    成功解决 RuntimeError Attempting to deserialize object on CUDA device 1 but torch cuda device count is 1 报错内容 程序在这一步报错 check
  • Android kotlin自定义自动换行LinearLayout

    目录 1 概述 2 实现步骤 3 kotlin自定义自动换行LinearLayout核心代码实现功能 3 1自定义LinearLayout
  • spring快速入门

    1 导入坐标
  • stack容器

    stack容器 1 stack 基本概念 概念 stack是一种先进后出 First In Last Out FILO 的数据结构 它只有一个出口 栈中只有顶端的元素才可以被外界使用 因此栈不允许有遍历行为 栈中进入数据称为 入栈 push
  • dll load failed: 找不到指定的模块_【已解决】“由于找不到xinput1_3.dll,无法继续执行代码”...

    许多小伙伴在玩游戏或者使用电脑的过程中 电脑突然提示 由于找不到xinput1 3 dll 无法继续执行代码 导致游戏等程序无法正常启动运行 并且导致电脑系统弹窗报错 那xinput1 3 dll丢失怎么修复呢 下面让小编手把手教你解决方法
  • CentOS7安装OpenStack(Liberty)

    1 安装yum源 yum install https buildlogs centos org centos 7 cloud x86 64 openstack liberty centos release openstack liberty
  • 百度智能云千帆大模型三连击:接入LLaMA2等33个模型、上线插件功能和103个Prompt模板

    作为全球首个一站式企业级大模型平台 百度智能云 千帆大模型平台 在提供包括文心一言在内的大模型服务及第三方大模型服务的同时 还提供大模型开发和应用的整套工具链 帮助企业解决大模型从训练到开发过程中的全链条问题 自2023年3月发布以来 千帆
  • 看懂android中的adapter适配器

    首先需要知道一共有4个文件 fragment类 adapter fragment的布局文件 adapter中的item的布局文件 1 首先声明一个控件 RecyclerView 2 然后声明一个adapter类 3 在initView 上
  • python中typeerror_详解python中的TypeError错误解决办法

    新手在学习python时候 会遇到很多的坑 下面来具体说说其中一个 在使用python编写面向对象的程序时 新手可能遇到TypeError this constructor takes no arguments这个错误 例如下面的程序 cl
  • gtest 单元测试工具的基本使用

    gtest 单元测试 gtest 简介 gtest 优点 安装 gtest 测试 demo 总结 gtest 简介 gtest是Google的一套用于编写C 测试的框架 可以运行在很多平台上 包括Linux Mac OS X Windows
  • 获取时间和脸颊、下颚线灯模式

    电流检测的应用 电路检测电路常用于 高压短路保护 电机控制 DC DC换流器 系统功耗管理 二次电池的电流管理 蓄电池管理等电流检测等场景 对于大部分应用 都是通过感测电阻两端的压降测量电流 一般使用电流通过时的压降为数十mV 数百mV的电
  • android动画内存优化,Android 性能优化之内存优化

    定义 内存泄漏 Memory Leak 指 程序在申请内存后 当该内存不需再使用但却无法被释放的现象 内存溢出 OOM 应用程序所需的内存超出了为其分配的内存限额 Android将进程分为5个优先等级 前台进程 可见进程 服务进程 后台进程
  • google.api.http

    Http 定义api服务的http配置 它包含一个httprule列表 每个列表指定一个rpc方法到一个或多个http rest api方法的映射 字段 描述 rules HttpRule 一个适用于各个API方法的http配置规则列表 注
  • 编译优化之 - 向量化优化入门

    1 介绍 2 Intel高级向量扩展 3 GCC中向量化 4 ICC中向量化 5 AOCC LLVM中向量化 1 介绍 什么是自动向量化 自动向量化 automatic vectorization 是自动并行化 automatic para
  • STM32笔记:高精度脉冲宽度计 双输入捕获+DMA方式

    本文介绍如何用STM32F107VC Waveshare Open107V实验板 实现高精度的脉冲宽度计 占空比 开发环境 IDE STM32CubeIDE 1 8 固件库 STM32Cube FW F1 V1 8 4 函数发生 RIGOL
  • 人工智能开源社区论坛----开源助力多领域AI生态发展

    ChinaOSC 2022 人工智能开源社区论坛 开源助力多领域AI生态发展技术论坛将于2022年8月20日13 00 17 00在陕西省西安高新国际会议中心召开 本论坛将围绕 开源社区助力多领域AI生态发展 主题 邀请AI开源领域顶级技术
  • Filco圣手二代键盘蓝牙连接方法

    键盘前面的电源按钮按进去 即打开电源开关 同时按下Ctrl Alt Fn 看到蓝灯和红灯同时亮起 之后剩蓝灯闪烁 按下小键盘中数字键1 4中的一个 一共可以连4台设备 如果你选的数字之前连接过其他设备 可以在第2步做完之后先按两秒清除按钮
  • 托福综合写作套路

    1 文章认定 教授驳斥 2 The reading passage provides three possible functions of the carved stone balls However in the lecture the
  • 决策树算法原理+例题练习

    一 决策树的优缺点 优点 计算复杂度不高 输出结果易于理解 对中间值的缺失值不敏感 可以处理不相关特征数据 缺点 可能会产生过度匹配的问题 使用数据类型 数值型和标称型 二 一个实例 一天 老师问了个问题 只根据头发和声音怎么判断一位同学的