不使用递归的决策树生成算法

不使用递归的决策树生成算法

    利用队列 queue ,实现层次遍历(广度优先遍历),逐步处理每个节点来建立子树结构。再构建一个辅助队列,将每个节点存储到 nodes_to_process 列表中,以便在树生成完成后可以反向遍历计算每个节点的 leaf_num(叶子节点数量)。对于每个节点,根据特征选择和树的条件构建子节点;如果达到叶节点条件,直接将其标记为叶节点。最后,逆序处理计算每个结点的叶节点数量:通过逆序遍历 nodes_to_process 列表(即从叶节点到根节点),每次更新父节点的 leaf_num 为其所有子节点 leaf_num 的总和。

    在构建决策树的过程中,每个节点都会根据特征选择和树的构建条件来决定是否进一步分裂。以下是这个步骤的详细说明:
1 、当前节点的特征选择
对于每个节点 current_node ,需要从剩余的特征集合 A 中选择一个“最优特征” a ,用于将数据集 D 划分成不同的子集。这个“最优特征”由基尼指数、信息增益或信息增率等来确定,使得划分后的子集在类别上更加纯净。
2 、判断是否满足叶节点条件
在进一步构建子节点之前,检查当前节点是否满足叶节点条件。如果满足以下任一条件,则将 current_node 标记为叶节点,而不再继续分裂:
1 单一类别 :如果数据集 D 中的所有样本都属于同一类 C ,则不再需要进一步划分。此时可以将 current_node 标记为叶节点,类别为 C
2 属性集为空或样本在剩余特征上取值相同 :如果 A 为空(即没有剩余特征可以选择),或数据集 D 中样本在剩余特征上的取值都相同,那么即使进一步分裂也不能提供更多信息。在这种情况下,current_node 也被标记为叶节点,并根据 D 中的样本数最多的类别作为 current_node 的类别。
3 达到最大深度 :如果当前节点的深度已经达到了预设的最大深度 MaxDepth ,则停止继续分裂,将 current_node 直接标记为叶节点,并将类别设为当前数据集中样本数最多的类别。
3 、构建子节点
如果不满足叶节点条件,则 current_node 将根据选择的特征 a 来生成子节点。分情况处理:
1 )当前特征为离散值:如果 a 是一个离散特征,节点会针对 a 的每个可能的取值创建一个子节点 child_node ,表示 a 取该值的样本子集。将数据集中所有在 a 上取值为 a ∗v的样本(记作Da =a ∗v)分配到 child_node ,并继续构建树。 如果D a =a ∗v为空,即该子集没有样本,说明该特征值在当前分支下没有样本。此时,将 child_node 标记为叶节点,并将其类别设为当前数据中出现次数最多的类别。如果D a =a ∗v不为空,则将 child_node 和该子集继续加入到构建队列中。
2 )当前特征为连续值:如果 a 是一个连续特征,则会根据分割点(采用二分法选取)将数据集划分为两个子集。构建两个子节点:一个子节点代表 a split_valuea 的样本子集;另一个子节点代表 a <split_valuea 的样本子集。将两个子节点及其对应的数据集加入到构建队列中,继续后续的树构建。
4 、将子节点添加到树中
每个 child_node 会作为 current_node 的子节点,存储在 current_node.subtree 中。通过这种方式,不断将子节点加入树中,直到所有节点都满足叶节点条件,不再继续分裂为止。
5 、完成子节点分裂后的后续处理
当队列中所有节点都处理完后,逆序遍历已处理的节点列表,计算每个节点的叶节点数。

不使用递归的建树算法的实现思路

    创建两个队列,分别为 queue nodes_to_process queue = deque([(root, X, y)]) 用来存储节点和数据,queue 的结构为三元组,分别为根节点、当前节点的 X 值,即去除 a 属性后剩下的 X 值,以及 y 标签。 nodes_to_process = [] 记录所有节点以便后续计算 leaf_num 。遍历 queue 队列,创建根节点并将其放入队列,并将当前节点存入 nodes_to_process以记录节点。使用 queue 按层次处理每个节点。
    每次处理时,首先检查是否达到叶节点条件(如最大深度或单一类别),如果是则标记为叶节点。如果不是叶节点,则选择最佳分割特征,并根据特征类型(离散或连续)生成对应的子节点。
    queue 队列处理完毕后,通过 nodes_to_process 逆序遍历,每个节点的 leaf_num 设为其子节点的 leaf_num 总和。

代码实现

    def generate_tree(self, X, y):root = Node()root.high = 0  # 根节点的高度为0queue = deque([(root, X, y)])  # 使用队列来存储节点和数据nodes_to_process = []  # 记录所有节点以便后续计算 leaf_numwhile queue:current_node, current_X, current_y = queue.popleft()nodes_to_process.append(current_node)# 叶节点条件:达到最大深度或只有单一类别或没有特征if current_node.high >= self.MaxDepth or current_y.nunique() == 1 or current_X.empty:current_node.is_leaf = Truecurrent_node.leaf_class = current_y.mode()[0]current_node.leaf_num = 1  # 是叶子节点,叶子数量为 1continue# 选择最佳划分特征best_feature_name, best_impurity = self.choose_best_feature_to_split(current_X, current_y)current_node.feature_name = best_feature_namecurrent_node.impurity = best_impurity[0]current_node.feature_index = self.columns.index(best_feature_name)feature_values = current_X[best_feature_name]if len(best_impurity) == 1:  # 离散值特征current_node.is_continuous = Falseunique_vals = feature_values.unique()sub_X = current_X.drop(best_feature_name, axis=1)for value in unique_vals:child_node = Node()child_node.high = current_node.high + 1queue.append((child_node, sub_X[feature_values == value], current_y[feature_values == value]))current_node.subtree[value] = child_nodeelif len(best_impurity) == 2:  # 连续值特征current_node.is_continuous = Truecurrent_node.split_value = best_impurity[1]up_part = '>= {:.3f}'.format(current_node.split_value)down_part = '< {:.3f}'.format(current_node.split_value)child_node_up = Node()child_node_down = Node()child_node_up.high = current_node.high + 1child_node_down.high = current_node.high + 1queue.append((child_node_up, current_X[feature_values >= current_node.split_value],current_y[feature_values >= current_node.split_value]))queue.append((child_node_down, current_X[feature_values < current_node.split_value],current_y[feature_values < current_node.split_value]))current_node.subtree[up_part] = child_node_upcurrent_node.subtree[down_part] = child_node_down# 逆序遍历 nodes_to_process,计算每个节点的 leaf_numwhile nodes_to_process:node = nodes_to_process.pop()if node.is_leaf:node.leaf_num = 1else:node.leaf_num = sum(child.leaf_num for child in node.subtree.values())return root

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

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

相关文章

自动驾驶系列—自动驾驶如何实现厘米级定位?深入解读GPS/RTK技术与应用

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

DevOps业务价值流:需求设计最佳实践

DevOps实践正推动着产品快速迭代与高质量交付&#xff0c;但需求设计作为产品开发的关键起点&#xff0c;往往被忽视。它不仅是收集与分析需求的过程&#xff0c;更是将需求转化为可实施产品特性的核心。本文深入探讨DevOps业务价值流中的需求设计&#xff0c;从调研、整理、原…

【MySQL】数据库整合攻略 :表操作技巧与详解

前言&#xff1a;本节内容讲述表的操作&#xff0c; 对表结构的操作。 是对表结构中的字段的增删查改以及表本身的创建以及删除。 ps&#xff1a;本节内容本节内容适合安装了MySQL的友友们进行观看&#xff0c; 实操更有利于记住哦。 目录 创建表 查看表结构 修改表结构 …

python可视化进阶

引用&#xff1a; 首先需要安装 plotnine from plotnine import* import joypy数据可视化进阶操作 3.1 类别数据可视化 【例3-1】——绘制简单条形图 【代码框3-1】——绘制简单条形图 # 图3-1的绘制代码 import pandas as pd import matplotlib.pyplot as plt from cvxpy …

使用 GitHub Actions 部署到开发服务器的详细指南

使用 GitHub Actions 部署到开发服务器的详细指南 在本篇博客中&#xff0c;我们将介绍如何使用 GitHub Actions 实现自动化部署&#xff0c;将代码从 GitHub 仓库的 dev 分支自动部署到开发服务器。通过这种方式&#xff0c;可以确保每次在 dev 分支推送代码时&#xff0c;服…

冒泡选择法(c基础)

适合对象c语言初学者。 冒泡选择法 作用对一个数组进行排序。&#xff08;介绍一下数组(c基础)(详细版)-CSDN博客&#xff09; 核心要点 1: 数组元素个数 sz 2: 比较后的交换。 核心思路 进行&#xff08;sz - 1&#xff09;趟&#xff0c;每一趟把最大数的放到末尾。其…

量子计算及其在密码学中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 量子计算及其在密码学中的应用 量子计算及其在密码学中的应用 量子计算及其在密码学中的应用 引言 量子计算概述 定义与原理 发展…

【论文笔记】Wings: Learning Multimodal LLMs without Text-only Forgetting

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Wings: Learning Multimod…

数据类型底层

计算机的工作原理 CPU 找数据 数据通过地址信息来标记 高级语言:在内存中"分配"空间用变量来标识 所以变量一定是存在地址的 例如: int a10; //a就是变量名用来对地址进行标识 0x100对这个地址标识必备常识:8bit1byte 常见的数据类型: char short int long //…

【Leecode】Leecode刷题之路第45天之跳跃游戏II

题目出处 45-跳跃游戏II-题目出处 题目描述 个人解法 思路&#xff1a; todo代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo官方解法 45-跳跃游戏II-官方解法 这道题是典型的贪心算法&#xff0c;通过局部最优解得到全局最优解。以下两种方法都是…

证件照尺寸168宽240高,如何手机自拍更换蓝底

在提供学籍照片及一些社会化考试报名时&#xff0c;会要求我们提供尺寸为168*240像素的电子版证件照&#xff0c;本文将介绍如何使用“报名电子照助手”&#xff0c;借助手机拍照功能完成证件照的拍摄和背景更换&#xff0c;特别是如何将照片尺寸调整为168像素宽和240像素高&am…

Kafka生产者如何提高吞吐量?

1、batch.size&#xff1a;批次大小&#xff0c;默认16k 2、linger.ms&#xff1a;等待时间&#xff0c;修改为5-100ms 3、compression.type&#xff1a;压缩snappy 4、 RecordAccumulator&#xff1a;缓冲区大小&#xff0c;修改为64m 测试代码&#xff1a; package com.bigd…

【开源免费】基于SpringBoot+Vue.JS水果购物网站(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 065 &#xff0c;文末自助获取源码 \color{red}{T065&#xff0c;文末自助获取源码} T065&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

Linux下通过sqlplus连Oracle提示字符是乱码▒▒▒[

先参考https://www.cnblogs.com/wrencai/articles/4374451.html 理解下Oracle编码字符集的概念 如下图,刚开始连上是软吗▒▒▒[ 执行export NLS_LANGJAPANESE_JAPAN.AL32UTF8 (这个仅在当前会话起作用)如果好了,说明字符集是这个,不行在尝试别的字符集 如果要永久设置 vim …

多个NVR同时管理EasyNVR多品牌NVR管理工具/设备:IP常见问题解决方案

随着视频监控技术的不断发展&#xff0c;NVR&#xff08;网络视频录像机&#xff09;已经成为现代安防系统的重要组成部分。而为了更高效地管理多个品牌的NVR设备&#xff0c;EasyNVR这一多品牌NVR管理工具应运而生。然而&#xff0c;在实际使用过程中&#xff0c;尤其是在多个…

【C++】C++的单例模式、跟踪内存分配的简单方法

二十四、C的单例模式、跟踪内存分配的简单方法 1、C的单例模式 本小标题不是讨论C的语言特性&#xff0c;而是一种设计模式&#xff0c;用于确保一个类在任何情况下都只有一个实例&#xff0c;并提供一个全局访问点来获取这个实例。即C的单例模式。这种模式常用于资源管理&…

任务中心全新升级,新增分享接口文档功能,MeterSphere开源持续测试工具v3.4版本发布

2024年11月5日&#xff0c;MeterSphere开源持续测试工具正式发布v3.4版本。 在这一版本中&#xff0c;系统设置方面&#xff0c;任务中心支持实时查看系统即时任务与系统后台任务&#xff1b;接口测试方面&#xff0c;新增接口文档分享功能、接口场景导入导出功能&#xff0c;…

Python毕业设计选题:基于django+vue的荣誉证书管理系统

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 学生管理 教师管理 证书分类管理 荣誉证书管理 菜单列表…

Pr 视频过渡:沉浸式视频

效果面板/视频过渡/沉浸式视频 Video Transitions/Immersive Video Adobe Premiere Pro 的视频过渡效果中&#xff0c;沉浸式视频 Immersive Video效果组主要用于 VR 视频剪辑之间的过渡。 自动 VR 属性 Auto VR Properties是所有 VR 视频过渡效果的通用选项。 默认勾选&#x…

mongoDB的安装及使用

mongodb的安装可参考&#xff1a;Centos系统中mongodb的安装详解_centos安装mongodb-CSDN博客 不要下载最新的版本&#xff0c;新的版本中mongo命令无法使用&#xff0c;也就是安装后不能通过mongo命令登录&#xff0c;我这里使用5.0.30版本&#xff1b; mongodb安装成功后通过…