机器学习——决策树(三)预剪枝

观前提示:这是本人机器学习决策树内容的第三篇博客沿用了之前相关的代码,包括信息增益计算函数、结点类、预测函数和分类精度计算函数 

完整代码指路

DrawPixel/decisionTree.ipynb at main · ndsoi/DrawPixel (github.com)

前两篇博客详见“机器学习”专栏

使用方法:

方法一:一口气连接——执行是不会报错的

方法二:针对本节内容的代码块

notebook中我做了目录划分

与本节内容相关的代码块如下图:

本节没有用到的是 dotree函数和TreeGenerate函数,所以预剪枝的主要是替换了TreeGenerate的逻辑

1、含义

预剪枝:

剪枝是指在决策树生成过程中,对每个结点在划分前先进行估计,若当前结点的划分不能带来决策树泛化性能提升,则停止划分并将当前结点标记为叶结点

作用:提高构建决策树的效率、防止过拟合、提高模型的鲁棒性

2、实现流程

算法流程:

  1. 划分好训练集和验证集;
  2. 初始化根节点,标记为叶结点,用验证集计算精度,对当然结点进行划分,再用验证集计算精度,如果精度提升,则对当前结点进行划分,若精度无提升则不划分。

用一个队列(名为waitcheck)维护要考虑划分的结点。

step1:初始化根结点,将根结点投入到waitcheck中;

step2:从waitcheck中取出一个结点:

①当前结点是一个叶结点,计算验证集的分类精度a

②考虑当前结点能否在划分:

        若该结点可以划分,则找出它划分的最优属性,进行划分,再计算划分后的验证集预测效果b

                比较a和b的大小:

                        如果b比a小,则不划分,将该结点标记为叶结点,继续考虑waitcheck

                        如果b比a大,则将该结点标记为非叶结点,新生成的子结点加入waitcheck

        不行则考虑下一结点

step3:重复step2,直到waitcheck为空

3、编程实现

1、划分训练集和验证集

按照西瓜书的数据划分:


dataSet = [
        # 1
        ['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
        # 2
        ['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '好瓜'],
        # 3
        ['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
        # 4
        ['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '好瓜'],
        # 5
        ['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
        # 6
        ['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '好瓜'],
        # 7
        ['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', '好瓜'],
        # 8
        ['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', '好瓜'],

        # ----------------------------------------------------
        # 9
        ['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', '坏瓜'],
        # 10
        ['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', '坏瓜'],
        # 11
        ['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', '坏瓜'],
        # 12
        ['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', '坏瓜'],
        # 13
        ['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', '坏瓜'],
        # 14
        ['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', '坏瓜'],
        # 15
        ['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '坏瓜'],
        # 16
        ['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', '坏瓜'],
        # 17
        ['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', '坏瓜']
    ]
Attr = ['色泽', '根蒂', '敲击', '纹理', '脐部', '触感']

# 硬编码类别
class_dict = {'坏瓜':0,'好瓜':1}

# 将数据合并格式
D = []
for i in range(len(dataSet)):
  d = {}
  for j in range(len(Attr)):
    d[Attr[j]] = dataSet[i][j]
  d['Class'] = class_dict[dataSet[i][-1]]
  D.append(d)

print(D)

2、批量验证函数

# 精度计算
def calAccuracy(pred,data):
  n = len(data)
  re = 0
  for i in range(n):
    if pred[i] == data[i]['Class']:
      re+=1
  return re/n

# 返回预测结果和精度
def predict_v4(root_4,val_data):
  re = []
  for i in range(len(val_data)):
    re.append(predict_v2(val_data[i],root_v4))
  return re,calAccuracy(re,val_data)

3、结点是否能继续划分

# 若是否有划分的资格
def CanDivide(node_v4):
  if node_v4.isSameClass() == True:
    return False,[]

  boolre,Attr = node_v4.isNoAttr()
  if boolre == False:
    return True,Attr
  return False,[]

4、初始数据集生成根结点、初始化waitcheck

import queue
# 找出初始数据集的最多类
max,cal_class = calMaxClass(train_data,class_num)
# 构造训练集的根结点
root_v4 = Node(train_data,Attr,max,cal_class,class_num) 
# 标记根结点位叶结点
root_v4.label = 1

# 初始化waitcheck队列
waitcheck = queue.Queue()
waitcheck.put(root_v4)

5、预剪枝过程(核心) 

def train_v4(waitcheck,root_v4):
  node_v4 = waitcheck.get()
  # 用验证集算一下精度
  res_o,acc_o = predict_v4(root_v4,val_data) 

  divide,Attr_Div = CanDivide(node_v4)
  if divide == False:
    # 考虑下一个结点
    print("考虑下一个结点")
    return
  else:
    # 先将当前结点的label改为0
    node_v4.label = 0

    # 尝试划分结点
    # 选取最优属性
    attr,info = node_v4.bestAttr()
    # 获取划分好的数据集
    SubDataSets = info[attr]['Dv']
    SubInfo = info[attr]['Dv_info']


    # 生成子node
    # 保持子node
    savesubnode = []
    Attr = copy.deepcopy(Attr_Div)
    Attr.remove(attr)
    st = 0
    for value,subds in SubDataSets.items():
      # 因为假设是离散属性,所以新的self.attr必然要去掉已经选出的attr
      subnodeAttr = copy.deepcopy(Attr)
      # 获取已经算好的Dv的max和cal_class
      submax = SubInfo[st][0]
      subcal_class = SubInfo[st][1]
      st+=1

      # 生成新结点
      subnode = Node(subds,subnodeAttr,submax,subcal_class,class_num)
      subnode.setflag(attr)
      # 假设新结点都是叶子结点
      subnode.label = 1

      # 暂存取得的新结点,若确定要划分,才加入讨论队列
      savesubnode.append(subnode)

      # 父结点记录子结点的指引
      node_v4.addsubDs(subnode,value)


    # 验证集评估
    res_d,acc_d = predict_v4(node_v4,val_data)
    print(f"未划分时的分类精度:{acc_o},划分后的分类精度:{acc_d}")
    print(f"展示一下划分后的树")
    drawTree(root_v4)
    if acc_d>acc_o:
      # 划分后的精度更高,所以划分
      # 将新的子结点加入waitcheck
      for i in savesubnode:
        # i.label = 0 不用改,取出来还要再令label=1
        waitcheck.put(i)
    else:
      # 划分后验证集的预测结果
      print("划分后验证集预测结果")
      print(res_d)
      # 最终还是不划分
      node_v4.label = 1

6、训练

while waitcheck.empty()==False:
    train_v4(waitcheck,root_v4)

drawTree(root_v4)

4、结果显示

1)对原始数据集考虑划分:可以看到在计算机计算精度内,色泽和脐部属性的信息增益是一样的,但遍历的时候脐部在后,而要求是大于等于最大信息增益的属性就可以替换为最优,所以初次划分的最优属性是脐部

2)按照脐部划分后,验证集评估模型发现划分后的分类精度是0.75,划分前的精度是0.375,所以不剪枝,将新增的子结点加入waitcheck

3)继续考虑新的结点,按照添加顺序应该是“脐部=凹陷”的数据集,该数据集的最优属性划分(看蓝色箭头),在计算机精度内后来者居上最优的属性是“纹理”,然后看下方绿色线,发现按照“纹理”划分,精度又从0.75提升至0.875,因此又保留了“纹理”产生的分支

4)继续考虑waitcheck的数据,发现这些结点再划分都不会使得模型在验证集的精度提升,于是决策树模型完全形成

最终的决策树是:

5、讨论:

这个预剪枝的结果与《机器学习》上的并不一致

原因:就是在最优属性划分上:同样的信息增益,西瓜书的选择是“色泽”,我的程序选择的是“纹理”,当用验证集验证的时候,“色泽”划分会导致正确性下降,而纹理却能继续提升分类精度

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

水泥领域智慧工厂物联网解决方案

水泥领域智慧工厂物联网解决方案 在水泥生产行业中,构建智慧工厂物联网解决方案已经成为推动产业升级、实现智能制造的关键路径。该方案深度融合了先进的信息技术与传统的水泥生产工艺,通过全面感知、可靠传输、智能处理等环节,实现了对整个…

Macos docker安装达梦数据库

官网下载达梦docker镜像安装包 导入安装包 docker load -i /Users/yeungsinsin/Downloads/dm8_20230808_rev197096_x86_rh6_64_single.tar查看导入的镜像 docker images4. docker run 启动容器 docker run -d -p 30236:5236 --restartalways --name dm8 --privilegedtrue -e…

是德科技keysight N9917A微波分析仪

181/2461/8938产品概述: N9917A 是一款使用电池供电的便携式分析仪;基本功能是电缆和天线分析;配置还包括频谱和网络分析仪、可选的内置功率计和矢量电压表。 N9917A FieldFox 手持式微波分析仪 主要特性和功能 18 GHz 最大频率&#xfef…

基于Springboot的闲置图书分享(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的闲置图书分享(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&…

MySQL的基础操作与管理

一.MySQL数据库基本操作知识: 1.SQL语句: 关系型数据库,都是使用SQL语句来管理数据库中的数据。 SQL,即结构化查询语言(Structured Query Language) 。 SQL语句用于维护管理数据库,包括数据查询、数据更新、访问控…

Sora底层技术原理:Stable Diffusion运行原理

AIGC 热潮正猛烈地席卷开来,可以说 Stable Diffusion 开源发布把 AI 图像生成提高了全新高度,特别是 ControlNet 和 T2I-Adapter 控制模块的提出进一步提高生成可控性,也在逐渐改变一部分行业的生产模式。惊艳其出色表现,也不禁好…

[BT]BUUCTF刷题第3天(3.21)

第3天(共4题) Web [极客大挑战 2019]LoveSQL Payload:/check.php?username1 union select 1,(select group_concat(password) from l0ve1ysq1),3%23&password1 看到登录页面,先尝试万能密码: 用户名&#xff…

Hive和Hadoop版本对应关系

通过 Downloads (apache.org) 即可查看

Java算法总结之插入排序(详解)

程序代码园发文地址:Java算法总结之插入排序(详解)-程序代码园小说,Java,HTML,Java小工具,程序代码园,http://www.byqws.com/ ,Java算法总结之插入排序(详解)http://www.byqws.com/blog/3148.html?sourcecsdn 插入排…

鸿蒙Harmony应用开发—ArkTS-全局UI方法(菜单)

在页面范围内关闭通过bindContextMenu属性绑定的菜单。 说明: 从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 ContextMenu.close 方法描述close(): void可以通过该方法在页面范围内关闭通过bindContextMenu给…

回归预测 | Matlab基于SAO-BiLSTM雪融算法优化双向长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SAO-BiLSTM雪融算法优化双向长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SAO-BiLSTM雪融算法优化双向长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SAO-B…

Linux课程五课---Linux调试器-gdb使用

作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 ​🎂 作者介绍: 🎂🎂 🎂 🎉🎉&#x1f389…

Django日志(一)

一、概念与配置 1.1、概述 日志是程序员经常在代码中使用快速和方便的调试工具。它在调试方面比print更加的优雅和灵活 而且日志记录对于调试很有用,可以提供更多,更好的结构化,有关应用程序的状态和运行状况的信息 Django框架的日志通过python内置的logging模块实现的,可…

【JavaScript 漫游】【040】Blob 对象

文章简介 本篇文章为【JavaScript 漫游】专栏的第 040 篇文章,对浏览器模型中的 Blob 对象进行了总结。 概述 Blob 对象表示一个二进制文件的数据内容,比如一个图片文件的内容就可以通过 Blob 对象读写。它通常用来读写文件,它的名字是 Bi…

BS4提取chrome.webdriver方法和属性以及描述并输出到Excel

BS4网络提取selenium.chrome.WebDriver类的方法及属性 chrome.webdriver: selenium.webdriver.chrome.webdriver — Selenium 4.18.1 documentation class selenium.webdriver.chrome.webdriver.WebDriver 是 Selenium 中用于操作 Chrome 浏览器的 WebDriver 类。WebDriver 类…

数据可视化-ECharts Html项目实战(4)

在之前的文章中,我们学习了如何创建圆环图、嵌套圆环图、蓝丁格尔玫瑰图。想了解的朋友可以查看这篇文章。同时,希望我的文章能帮助到你,如果觉得我的文章写的不错,请留下你宝贵的点赞,谢谢。 数据可视化-ECharts Htm…

鸿蒙一次开发,多端部署(二)从一个例子开始

本章通过一个天气应用,介绍一多应用的整体开发过程,包括UX设计、工程管理及调试、页面开发等。 UX设计 本示例中的天气应用包含主页、管理城市和添加城市三个页面,其中主页中又包含菜单和更新间隔两个弹窗,基本业务逻辑如下所示…

2024.3.21学习笔记

今日学习韩顺平java0200_韩顺平Java_对象机制练习_哔哩哔哩_bilibili 今日学习p246-p251 this关键词 java虚拟机会给每个对象分配this, 代表当前对象 this内存机制 this关键字可以用来访问类的属性、方法、构造器 this用以区分当前类的属性和局部变量 访问成员方法的语法…

《云计算:数字时代的引擎》

在数字化时代,云计算技术以其强大的计算能力和灵活的应用方式,成为推动各行各业发展的引擎。本文将围绕云计算的技术进展、技术原理、行业应用案例、面临的挑战与机遇以及未来趋势进行详细探讨。 云计算的技术进展 云计算的技术进展涵盖了多个方面&…

Redis入门到入坑(二)

Redis入门到入坑(二) Redis 数据持久化简介Rdb方式持久化Aof方式数据持久化 Redis事务处理Redis事务简介Redis事务控制实践 Redis架构设计Redis主从复制Redis哨兵模式Redis集群高可用 Redis在SpringBoot工程中的综合应用业务描述准备工作业务逻辑代码设计…