基于信息增益和基尼指数的二叉决策树

news/2024/11/7 11:08:01/文章来源:https://www.cnblogs.com/h4o3/p/18531757
# coding: UTF-8
'''
基于信息增益和基尼指数的二叉决策树的实现。
该决策树可以用于分类问题,通过选择合适的特征来划分样本。
'''from collections import Counterclass biTree_node:'''二叉树节点定义每个节点可以是叶子节点或内部节点。'''def __init__(self, f=-1, fvalue=None, leafLabel=None, l=None, r=None, splitInfo="gini"):'''类初始化函数para f: int, 切分的特征,用样本中的特征次序表示para fvalue: float or int, 切分特征的决策值para leafLabel: int, 叶节点的标签para l: biTree_node指针, 当前节点的左子树para r: biTree_node指针, 当前节点的右子树para splitInfo: string, 切分的标准, 可取值'infogain'和'gini', 分别表示信息增益和基尼指数。每个节点都保存了其用于划分的特征以及该特征的具体值,并且指向其左右子树。如果是叶子节点,则保存了该节点的标签。'''self.f = f  # 特征索引,即样本中的特征次序self.fvalue = fvalue  # 特征切分值,用于决定样本走向左子树还是右子树self.leafLabel = leafLabel  # 如果是叶节点,则保存对应的类别标签self.l = l  # 左子树,指向当前节点的左子节点self.r = r  # 右子树,指向当前节点的右子节点self.splitInfo = splitInfo  # 切分标准,用于决定使用何种方法来计算最佳特征和特征值def gini_index(samples):'''计算基尼指数。para samples: list, 样本列表,每个样本的最后一个元素是标签。return: float, 基尼指数。'''label_counts = sum_of_each_label(samples)total = len(samples)gini = 1.0for label in label_counts:prob = label_counts[label] / totalgini -= prob ** 2return ginidef info_entropy(samples):'''计算信息熵。para samples: list, 样本列表,每个样本的最后一个元素是标签。return: float, 信息熵。'''label_counts = sum_of_each_label(samples)total = len(samples)entropy = 0.0for label in label_counts:prob = label_counts[label] / totalentropy -= prob * (prob * 3.321928094887362)  # 以2为底的对数return entropydef split_samples(samples, feature, value):'''根据特征和值分割样本集。para samples: list, 样本列表。para feature: int, 特征索引。para value: float or int, 特征值。return: tuple, 两个列表,分别为左子集和右子集。'''left = [sample for sample in samples if sample[feature] < value]right = [sample for sample in samples if sample[feature] >= value]return left, rightdef sum_of_each_label(samples):'''统计样本中各类别标签的分布。para samples: list, 样本列表。return: dict, 标签及其出现次数的字典。'''labels = [sample[-1] for sample in samples]return Counter(labels)def build_biTree(samples, splitInfo="gini"):'''构建二叉决策树para samples: list, 样本的列表,每样本也是一个列表,样本的最后一项为标签,其它项为特征。para splitInfo: string, 切分的标准,可取值'infogain'和'gini', 分别表示信息增益和基尼指数。return: biTree_node, 二叉决策树的根节点。该函数递归地构建决策树,每次选择一个最佳特征和其值来切分样本集,直到无法有效切分为止。'''# 如果没有样本,则返回空节点if len(samples) == 0:return biTree_node()# 检查切分标准是否合法if splitInfo != "gini" and splitInfo != "infogain":return biTree_node()bestInfo = 0.0  # 最佳信息增益或基尼指数减少量bestF = None  # 最佳特征bestFvalue = None  # 最佳特征的切分值bestlson = None  # 左子树bestrson = None  # 右子树# 计算当前集合的基尼指数或信息熵curInfo = gini_index(samples) if splitInfo == "gini" else info_entropy(samples)sumOfFeatures = len(samples[0]) - 1  # 样本中特征的个数for f in range(0, sumOfFeatures):  # 遍历每个特征featureValues = [sample[f] for sample in samples]  # 提取特征值for fvalue in featureValues:  # 遍历当前特征的每个值lson, rson = split_samples(samples, f, fvalue)  # 根据特征及其值切分样本# 计算分裂后两个集合的基尼指数或信息熵if splitInfo == "gini":info = (gini_index(lson) * len(lson) + gini_index(rson) * len(rson)) / len(samples)else:info = (info_entropy(lson) * len(lson) + info_entropy(rson) * len(rson)) / len(samples)gain = curInfo - info  # 计算增益或基尼指数的减少量# 找到最佳特征及其切分值if gain > bestInfo and len(lson) > 0 and len(rson) > 0:bestInfo = gainbestF = fbestFvalue = fvaluebestlson = lsonbestrson = rson# 如果找到了最佳切分if bestInfo > 0.0:l = build_biTree(bestlson, splitInfo)  # 递归构建左子树r = build_biTree(bestrson, splitInfo)  # 递归构建右子树return biTree_node(f=bestF, fvalue=bestFvalue, l=l, r=r, splitInfo=splitInfo)else:# 如果没有有效切分,则生成叶节点label_counts = sum_of_each_label(samples)return biTree_node(leafLabel=max(label_counts, key=label_counts.get), splitInfo=splitInfo)def predict(sample, tree):'''对给定样本进行预测para sample: list, 需要预测的样本para tree: biTree_node, 构建好的分类树return: int, 预测样本所属的类别'''if tree.leafLabel is not None:  # 如果当前节点是叶节点return tree.leafLabelelse:# 否则根据特征值选择子树sampleValue = sample[tree.f]branch = tree.r if sampleValue >= tree.fvalue else tree.lreturn predict(sample, branch)  # 递归下去def print_tree(tree, level='0'):'''简单打印树的结构para tree: biTree_node, 树的根节点para level: str, 当前节点在树中的深度,0表示根,0L表示左子节点,0R表示右子节点'''if tree.leafLabel is not None:  # 如果是叶节点print('*' + level + '-' + str(tree.leafLabel))  # 打印标签else:print('+' + level + '-' + str(tree.f) + '-' + str(tree.fvalue))  # 打印特征索引及切分值print_tree(tree.l, level + 'L')  # 打印左子树print_tree(tree.r, level + 'R')  # 打印右子树if __name__ == "__main__":# 示例数据集:某人相亲的数据blind_date = [[35, 176, 0, 20000, 0],[28, 178, 1, 10000, 1],[26, 172, 0, 25000, 0],[29, 173, 2, 20000, 1],[28, 174, 0, 15000, 1]]print("信息增益二叉树:")tree = build_biTree(blind_date, splitInfo="infogain")  # 构建信息增益的二叉树print_tree(tree)  # 打印树结构print('信息增益二叉树对样本进行预测的结果:')test_sample = [[24, 178, 2, 17000],[27, 176, 0, 25000],[27, 176, 0, 10000]]# 对测试样本进行预测for x in test_sample:print(predict(x, tree))print("基尼指数二叉树:")tree = build_biTree(blind_date, splitInfo="gini")  # 构建基尼指数的二叉树print_tree(tree)  # 打印树结构print('基尼指数二叉树对样本进行预测的结果:')# 再次对测试样本进行预测for x in test_sample:print(predict(x, tree))  # 预测并打印结果

输出结果:


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

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

相关文章

高级语言程序设计第六次个人作业

班级链接:https://edu.cnblogs.com/campus/fzu 作业要求链接:https://edu.cnblogs.com/campus/fzu/2024C/homework/13303 学号:102400130 姓名:杨子旭

【WPF开发】HandyControl Growl控件Error通知不自动消失的问题

Error类型的通知不自动消失,但是又需要他跟其他的统一。 那么翻翻代码看看为啥不消失呗 1、这是决定关闭通知的计时器2、这是通过_staysOpen来控制是否启动计时器 _staysOpen为true的时候就会不启动了3、明显看到Error中如果非IsCustom的情况下会_staysOpen那么最后,我们可以…

centos修改yum源

centos修改yum源 在CentOS中修改YUM源,你需要替换/etc/yum.repos.d/目录下的.repo文件。以下是一个基本的步骤和示例:备份当前的YUM源文件。创建或编辑一个新的.repo文件。添加你的YUM源信息。例如,如果你想要将YUM源更改为阿里云的源,可以按照以下步骤操作:# 1. 备份当前…

C# NET framework 4.5调用系统Toast通知

C# Toast 资源调用dll 资源调用exe最近有一个工控程序,基于net4.5.2开发的,尝试增加win10系统的Toast通知消息,网络收集到如下结论: 1. Toast功能需要net4.8的高版本,调用Microsoft.Toolkit.Uwp.Notifications.dll —— 工控程序不可能升级的 2. 低版本net都是使用winform…

C++ ftp上传文件

目录结构: ftpdemo/include/elapse.h1 /*************************************************2 Copyright (C), 2019-2029, Guide Tech. Co., Ltd.3 File name: elapse.h4 Author: henry5 Version: V1.0.0.0 6 Date: 202410087 Description:计算函数运行时间8 **************…

Schema Free

向量检索服务DashVector在设计上支持Schema Free。向量检索服务DashVector在设计上支持Schema Free,在插入Doc、更新Doc、插入或更新Doc时,可设置任意KeyValue结构的字段(Field),如下所示: Python示例: collection.insert(Doc(id=1,vector=np.random.rand(4),fields={name…

0基础读顶会论文—流程即服务(PraaS):通过无服务器流程统一弹性云和有状态云

细粒度的无服务器函数为许多新应用提供了动力,这些应用受益于弹性扩展和按需付费计费模型,同时将基础设施管理开销降至最低。为了实现这些特性,函数即服务(FaaS)平台将计算和状态分离,PraaS 通过提供数据本地性、快速调用和高效通信改进了当前的 FaaSAbstract 细粒度的无…

安装和配置CentOS9

安装和配置CentOS9 一、下载CentOS9镜像文件 1.访问官网:首先,你需要访问CentOS的官网或阿里云镜像网站 2.选择版本:在官网上,选择CentOS9的64位操作系统版本进行下载。3.等待下载:点击下载链接后,等待镜像文件下载完成。 二、安装CentOS9 1. 创建虚拟机(以VMware WorkS…

wed服务器一览

cs架构 c客户端 s服务端 bs架构 浏览器nb(客户端) 网站是做服务端客户端浏览器 到 服务器 请求 服务器 到 客户端浏览器 相应

WebSocket简介

一、websocket简介 websocket是一种在单个TCP连接上进行全双工通信的协议。 websocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向…

袋鼠云港口数智化解决方案发布,数智引领,加速“智变”丨2024袋鼠云秋季发布会回顾

2023年12月,交通运输部印发《关于加快智慧港口和智慧航道建设的意见》,《意见》贯穿了“3条主线”,其中最首要的主线是“数字化”,数字化是基础,必须通过数字赋能建设、生产、运营、管理、服务的全要素、全过程、全场景,将数据作为新的生产要素,方可夯实智慧港口和智慧航…