id3算法【python,算法,机器学习】

ID3 算法, 即 Iterative Dichotomiser 3(迭代二分器第三代)。算法通过迭代地选择具有最高信息增益的特征来分割数据集,从而递归地生成决策树模型,直至数据集被完美分类或无可分割的特征为止。

ID3 构建决策树的流程:

  1. 找到最优特征(信息增益值最高)。
  2. 最优特征,特征值作为有向边,判断子数据集
    • 全部是同一类:输出叶子节点。
    • 多类:
      • 如果子数据集中还有特征,那么再次找寻最优特征。
      • 如果子数据集中只剩下最后的分类结果了,那么输出最多的一类作为叶子节点。
  3. 直到叶子节点全部输出,或者无数据可遍历。

ID3 算法的特点:

  1. 只能处理离散型数据的学习计算。不能处理连续型数据。
  2. 容易产生过拟合现象(overfitting),泛化能力弱。

使用到的公式

  1. 信息熵(Entropy) H ( X ) = − ∑ i = 1 n p i log ⁡ 2 p i H(X)=-\sum\limits_{i=1}^{n} p_i\log_{2}{p_i} H(X)=i=1npilog2pi 其中, X X X表示样本, p i p_i pi表示概率,并且 ∑ i = 1 n p i = 1 \sum\limits_{i=1}^{n}p_i=1 i=1npi=1。例如投掷硬币,正面朝上的概率为1/2,反面朝上的概率为1/2,那么 H ( X ) = − ( 1 2 log ⁡ 2 1 2 + 1 2 log ⁡ 2 1 2 ) = 1 H(X)=-(\frac{1}{2}\log_2\frac{1}{2}+\frac{1}{2}\log_2 \frac{1}{2})=1 H(X)=(21log221+21log221)=1
  2. 条件熵(Condition Entropy) H ( Y ∣ X ) = ∑ p i H ( Y ∣ X = x i ) H(Y|X)=\sum p_iH(Y|X=x_i) H(YX)=piH(YX=xi) 表示在 X 发生的前提下,Y 的信息熵。
  3. 信息增益(Information Gain) G ( D ∣ A ) = H ( D ) − H ( D ∣ A ) G(D|A)=H(D)-H(D|A) G(DA)=H(D)H(DA) 表示 A 发生时,的信息增益。

下面将按照如下步骤实现一个简单的 ID3 决策树:

  1. 准备训练数据。
  2. 从可选的特征中选出一个最佳特征作树的节点。
    • 先计算数据中的初始熵。
    • 然后计算每个特征下的信息熵。
    • 计算各个特征的熵增,熵增最大的将作为树的节点。
  3. 根据选择出的特征节点,对数据进行分组,对于每个分组,计算其信息熵,选择出信息熵最小的分组值作为决策特征值,然后获取该特征值对应的y值。
  4. 将非最小熵值的其他分组作为树的子节点,重复 2 - 3 步骤,继续构建决策树。

实例代码如下:

import numpy as np
import pandas as pd
from pandas import DataFrame# 计算 D 的信息熵
def cal_h(p_arr):return sum(-p * np.log2(p) for p in p_arr)# 计算分组的信息熵
def cal_grouped_h(groups_p):return dict((k, cal_h(p_arr)) for k, p_arr in groups_p.items())def cal_c_h(p_arr_info):"""计算条件熵:param p_arr_info:输入的概率信息,字典类型,对应的值用列表表示,列表的第一个元素表示该条件在整体样本中的概率,从第二个元素开始,表示该条件下各个分量的概率:return: 条件熵的总和"""return np.sum([p_arr[0] * cal_h(p_arr[1:]) for p_arr in p_arr_info.values()])# 根据特征值进行分组,对每个分组中 y_label 的概率进行统计
def stat_y_label_percentage(df: DataFrame, feature, y_label, is_to_dict=False):condition_stat = df.groupby(feature)[y_label].value_counts(normalize=True).to_frame(name='percentage').reset_index()if is_to_dict:return condition_stat.groupby(feature)['percentage'].apply(list).to_dict()return condition_stat# 计算各个特征的条件信息熵
def cal_features_c_h(df, features, y_label):result = {}for feature in features:# 根据特征值分组,对每个分组中 y_label 的概率进行统计grouped_p_items = stat_y_label_percentage(df, feature, y_label,is_to_dict=True)print(f"'{feature}'的概率分布:{grouped_p_items}")# 计算各个分组占总体样本的概率grouped_p = df[feature].value_counts(normalize=True).to_dict()# 将分组概率插入到各组概率数组的第一项中[grouped_p_items[k].insert(0, p) for k, p in grouped_p.items()]# 计算特征下的条件熵c_h = cal_c_h(grouped_p_items)print(f"'{feature}'的条件熵为:{c_h}")result[feature] = c_hreturn result# 计算熵增
def cal_gain_entropy(pre_entropy, cur_entropy: dict):return dict((k, pre_entropy - v) for k, v in cur_entropy.items())# 熵增最大的特征,作为节点
def select_max_gain_entropy(entropy_gain_info):return max(entropy_gain_info.items(), key=lambda x: x[1])[0]# 定义决策树
class DecisionTree:y_label = Nonedef __init__(self, df, features, y_label):self.y_label_val = Noneself.decision_condition_val = Noneself.other_y_label_val = Noneself.df = dfself.features = featuresself.children = []self.y_label = y_labeldef select_decision_node(self):# 计算初始信息熵percentages = self.df[self.y_label].value_counts(normalize=True)h_D = cal_h(percentages)# 计算信息熵info_h = cal_features_c_h(self.df, self.features, self.y_label)# 计算熵增gain_entropy = cal_gain_entropy(h_D, info_h)print(gain_entropy)# 选择熵增最大的节点作为分割点select_node = select_max_gain_entropy(gain_entropy)print(select_node)# 构造树的节点self.name = select_node# 计算决策值,即获取决策值,和对应的训练值def cal_decision_val(self):grouped_p = stat_y_label_percentage(self.df, self.name, self.y_label,True)grouped_h = cal_grouped_h(grouped_p)# 熵值最小的值作为叶子的判断条件self.decision_condition_val = min(grouped_h.items(),key=lambda x: x[1])[0]# 决策条件下的概率数据,即 yes 和 no 的占比decision_condition_data = self.df[self.df[self.name] ==self.decision_condition_val]decision_condition_data_p = stat_y_label_percentage(decision_condition_data, self.name,self.y_label)# 概率大的作为预测值self.y_label_val = self.df.loc[decision_condition_data_p["percentage"].idxmax(),self.y_label]# 临时变量,当没有子节点时,预测树的另一个分支值self.temp_other_y_label_val = "no" if self.y_label_val == 'yes' else "yes"def create_children(self):# 树的分支,需要排除已经决策的点children_nodes = [val for val in self.df[self.name].unique() ifval != self.decision_condition_val]self.features.remove(self.name)if self.features:for node in children_nodes:child_df = self.df[self.df[self.name] == node].reset_index(drop=True)child = DecisionTree(child_df, self.features, self.y_label)child.fit()self.children.append(child)# 当特征值为空时,停止添加子树if not self.features:break# 当无特征时,直接决策else:self.other_y_label_val = self.temp_other_y_label_val# 训练决策树def fit(self):# 选择决策点self.select_decision_node()# 计算当前节点的决策self.cal_decision_val()# 递归构建树self.create_children()# 决策def decide(self, row):if row[self.name] == self.decision_condition_val:row[self.y_label] = self.y_label_valelse:if not self.children:row[self.y_label] = self.other_y_label_valelse:for child in self.children:child.decide(row)if __name__ == '__main__':df = pd.DataFrame({"outlook":["overcast", "overcast", "overcast", "overcast","rainy", "rainy", "rainy", "rainy", "rainy","sunny", "sunny", "sunny", "sunny", "sunny"],"temperature": ["hot", "cool", "mild", "hot", "mild","cool", "cool", "mild","mild", "hot", "hot", "mild", "cool","mild"],"humidity": ["high", "normal", "high", "normal", "high","normal", "normal", "normal","high", "high", "high", "high", "normal","normal"],"windy": ["FALSE", "TRUE", "TRUE", "FALSE", "FALSE", "FALSE","TRUE", "FALSE", "TRUE", "FALSE","TRUE", "FALSE", "FALSE", "TRUE"],"play": ["yes", "yes", "yes", "yes", "yes", "yes", "no","yes", "no", "no", "no", "no", "yes","yes"]})tree = DecisionTree(df, ["outlook", "temperature", "humidity", "windy"],"play")# 训练tree.fit()test_df = df = pd.DataFrame({"outlook": ["rainy", "sunny"],"temperature": ["hot", "cool"],"humidity": ["high", "high"],"windy": ["TRUE", "TRUE"],"play": ["", ""]})# 决策for _, row in df.iterrows():tree.decide(row)print(test_df)

上述代码是一个简单的 ID3 决策树实现,你可以根据实际情况,对测试数据进行适当的修改,然后使用决策树进行训练和预测。

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

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

相关文章

怎么检查阿里云的ECS机器上是不是有GPU资源

要检查阿里云 ECS 实例上是否有 GPU 资源,可以使用以下命令: lspci | grep -i nvidia这个命令将显示与 NVIDIA GPU 相关的信息。如果有输出,表示你的 ECS 实例上存在 NVIDIA GPU 资源。 如果你无法找到 lspci 命令,你可能需要安…

GPT-4o流式数据处理 Extra data: line 3 column 1 (char 254

背景:新的大模型生成的流式数据是多个data在一起的输出,卧槽,难怪这么快的速度。 经研究发现还是有流式数据从中间切断了,具体如下示例: bdata: {"id":"chatcmpl","object":"chat.completion.chunk","created":17158…

路由引入实验(华为)

思科设备参考:路由引入实验(思科) 技术简介 路由引入技术在网络通信中起着重要的作用,能够实现不同路由协议之间的路由传递,并在路由引入时部署路由控制,实现路径或策略的控制 实验目的 不同的路由协议之…

python web自动化(Pytest实战)

1.UnitTest框架与Pytest框架对⽐ 1) unittest框架介绍 Unittest则是Python语⾔的标准单元测试框架。 Unittest⽀持⾃动化测试,测试⽤例的初 始化、关闭和测试⽤例的聚合等功能,它有⼀个很重要的特性&#xff…

FastThreadLocal 为什么那么快

在并发编程中,ThreadLocal提供了一种便捷的方式来存储线程独有的数据。然而,在高性能网络框架如Netty中,标准的ThreadLocal实现可能带来一定的性能开销。因此,Netty提供了FastThreadLocal作为替代方案,显著提升了性能。…

深度学习-转置卷积

转置卷积 转置卷积(Transposed Convolution),也被称为反卷积(Deconvolution),是深度学习中的一种操作,特别是在卷积神经网络(CNN)中。它可以将一个低维度的特征图&#x…

jar包读取properties配置文件错误,返回null

现象: 使用intellij Idea编写java项目,debug调试时,使用redis.properties文件的类A,A的代码可以使用 “InputStream in RedisUtils.class.getClass().getResourceAsStream("/" proPath);” 方式正常读取redisConfig…

Java面试八股之有哪些线程安全的集合类

Java中有哪些线程安全的集合类 在Java中,并非所有的集合类都是线程安全的,但在多线程环境下,确保集合操作的线程安全性至关重要。以下是几个典型的线程安全集合类: Vector: 类似于ArrayList,但它是线程安全的。它通过…

搭建python环境

要想能够进行python开发,就需要搭建好python的环境。 需要安装的环境主要是两个部分: 运行环境:python 开发环境:pycharm 官方网站:https://www.python.org pycharm软件调节字体大小 pycharm 软件调节背…

QT C++ QTableWidget 演示

本文演示了 QTableWidget的初始化以及单元格值改变时响应槽函数,打印单元格。 并且,最后列不一样,是combobox ,此列的槽函数用lambda函数。 在QT6.2.4 MSVC2019 调试通过。 1.界面效果 2.头文件 #ifndef MAINWINDOW_H #define MAINWINDOW…

vue小记——小组件(1)

代码&#xff1a; <template><div><el-steps :active"active" finish-status"success" simple><el-step title"数据导入"><i class"fa fa-cloud-upload fa-icon-custom" slot"icon"></i…

【Python】—— 推导式

目录 &#xff08;一&#xff09;列表推导式 示例&#xff1a;创建一个0-10的列表 示例&#xff1a;带有条件的列表推导式 示例&#xff1a;多个for循环实现列表推导式 &#xff08;二&#xff09;字典推导式 &#xff08;三&#xff09;集合推导式 总结 &#xff08;一&a…

大语言模型预训练新前沿:「最佳适配打包」重塑文档处理标准

源自&#xff1a;机器之心 "人工智能技术与咨询“ 发布 声明:公众号转载的文章及图片出于非商业性的教育和科研目的供大家参考和探讨&#xff0c;并不意味着支持其观点或证实其内容的真实性。版权归原作者所有&#xff0c;如转载稿涉及版权等问题&#xff0c;请立即联系…

MySQL的自增ID连续性控制变量innodb_autoinc_lock_mode

查看 innodb_autoinc_lock_mode 的值 在 MySQL 命令行客户端中使用“SHOW VARIABLES”查看&#xff1a; MySQL [mydb]> SHOW VARIABLES LIKE innodb_autoinc_lock_mode; --------------------------------- | Variable_name | Value | -----------------------…

简单谈一下微服务

微服务&#xff0c;说这个之前我们先了解一下soa&#xff0c;这个十几年前的火热词汇&#xff0c;说实话&#xff0c;虽然我是一个计算机行业人士&#xff0c;但是很反感这种造词的风气&#xff0c;尤其是云里雾里&#xff0c;旧瓶装新酒的&#xff0c;作为一个it技术&#xff…

蓝桥杯第18489题——拔苗助长(质数+map)

问题描述 蓝桥村是蓝桥王国年年的模范村&#xff0c;这是因为他们村的稻田每年都是优美的。 对于一块稻田来说&#xff0c;如果其中任意两根不同的秧苗的高度乘积均为完全平方数&#xff0c;该稻田被称之为优美的稻田。 蓝桥王国的稻田验收日即将到来&#xff0c;但现在蓝桥…

BGP(一)边界网关协议

BGP协议基础 路由分类 直连路由 非直连路由&#xff08;间接路由&#xff09; 静态路由动态路由 IGP&#xff1a;内网网关路由协议&#xff08;在企业内部或数据中心内部使用&#xff09; DV&#xff1a;距离矢量路由协议RIP&#xff08;v1/v2&#xff09;IGRP——网络直径&…

【易生支付官网注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【会议征稿,IEEE独立出版】第四届计算机技术与信息科学国际研讨会(ISCTIS 2024)

第四届计算机技术与信息科学国际研讨会&#xff08;ISCTIS 2024)将于2024年7月12-14日在中国西安举行。大会将邀请国内外计算机技术与信息科学领域的知名专家学者出席会议&#xff0c;在大会上通过主题演讲、口头报告等方式与学者们分享最新研究成果、交流探讨学术难题。同时&a…

彩信JSON接口对接发送

随着通讯技术的飞速发展&#xff0c;传统的短信已经无法满足人们日益增长的沟通需求。在这样的背景下&#xff0c;群发彩信作为一种更为先进、更为丰富的信息传递方式&#xff0c;逐渐受到了企业和个人的青睐。那么&#xff0c;群发彩信应该怎么对接&#xff0c;又具体有哪些优…