11.29(2)

news/2025/11/29 23:51:00/文章来源:https://www.cnblogs.com/cyy1811068002/p/19287774

机器学习实验import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import math
import time

class Node:
"""
决策树节点类
"""
def init(self, is_leaf=False, label=None, feature=None, threshold=None, children=None):
self.is_leaf = is_leaf # 是否为叶节点
self.label = label # 叶节点的类别标签
self.feature = feature # 用于分割的特征索引
self.threshold = threshold # 连续特征的分割阈值
self.children = children if children else {} # 子节点字典

class C45DecisionTree:
"""
C4.5决策树算法实现,包含预剪枝和后剪枝功能
"""
def init(self, max_depth=None, min_samples_split=2, min_samples_leaf=1,
prune_method=None, confidence_threshold=0.05, use_pruning=True):
"""
初始化C4.5决策树

    参数:- max_depth: 树的最大深度,用于预剪枝- min_samples_split: 节点分裂所需的最小样本数,用于预剪枝- min_samples_leaf: 叶节点所需的最小样本数,用于预剪枝- prune_method: 剪枝方法,'pre'为预剪枝,'post'为后剪枝,None为不剪枝- confidence_threshold: 用于后剪枝的置信度阈值- use_pruning: 是否使用剪枝"""self.root = Noneself.max_depth = max_depthself.min_samples_split = min_samples_splitself.min_samples_leaf = min_samples_leafself.prune_method = prune_methodself.confidence_threshold = confidence_thresholdself.use_pruning = use_pruningdef entropy(self, y):"""计算熵"""if len(y) == 0:return 0# 计算各类别概率_, counts = np.unique(y, return_counts=True)probabilities = counts / len(y)# 计算熵entropy_value = -np.sum(probabilities * np.log2(probabilities))return entropy_valuedef information_gain_ratio(self, X, y, feature_idx, threshold=None):"""计算信息增益比"""# 计算原始熵original_entropy = self.entropy(y)# 如果是连续特征,需要根据阈值进行划分if threshold is not None:left_mask = X[:, feature_idx] <= thresholdright_mask = X[:, feature_idx] > thresholdleft_y, right_y = y[left_mask], y[right_mask]if len(left_y) == 0 or len(right_y) == 0:return -np.inf# 计算条件熵left_entropy = self.entropy(left_y)right_entropy = self.entropy(right_y)weight_left = len(left_y) / len(y)weight_right = len(right_y) / len(y)conditional_entropy = weight_left * left_entropy + weight_right * right_entropy# 计算信息增益information_gain = original_entropy - conditional_entropy# 计算分裂信息split_info = -weight_left * np.log2(weight_left) - weight_right * np.log2(weight_right)# 计算信息增益比if split_info == 0:return 0gain_ratio = information_gain / split_inforeturn gain_ratioelse:  # 离散特征unique_values = np.unique(X[:, feature_idx])weighted_entropy = 0split_info = 0for value in unique_values:mask = X[:, feature_idx] == valuesubset_y = y[mask]weight = len(subset_y) / len(y)weighted_entropy += weight * self.entropy(subset_y)split_info -= weight * np.log2(weight)information_gain = original_entropy - weighted_entropyif split_info == 0:return 0gain_ratio = information_gain / split_inforeturn gain_ratiodef find_best_split(self, X, y):"""寻找最佳分裂特征和阈值"""best_feature = Nonebest_threshold = Nonebest_gain_ratio = -np.infn_features = X.shape[1]for feature_idx in range(n_features):# 对连续特征寻找最佳阈值unique_values = np.unique(X[:, feature_idx])# 如果特征值较少,考虑作为离散特征处理if len(unique_values) <= 10:# 离散特征处理gain_ratio = self.information_gain_ratio(X, y, feature_idx)if gain_ratio > best_gain_ratio:best_gain_ratio = gain_ratiobest_feature = feature_idxbest_threshold = Noneelse:# 连续特征处理,尝试所有可能的阈值thresholds = (unique_values[:-1] + unique_values[1:]) / 2  # 取中间值作为候选阈值for threshold in thresholds:gain_ratio = self.information_gain_ratio(X, y, feature_idx, threshold)if gain_ratio > best_gain_ratio:best_gain_ratio = gain_ratiobest_feature = feature_idxbest_threshold = thresholdreturn best_feature, best_thresholddef majority_vote(self, y):"""多数投票确定类别"""if len(y) == 0:return Nonevalues, counts = np.unique(y, return_counts=True)return values[np.argmax(counts)]def build_tree(self, X, y, depth=0):"""递归构建决策树"""# 如果所有样本属于同一类别,创建叶节点if len(np.unique(y)) == 1:return Node(is_leaf=True, label=y[0])# 如果达到最大深度,创建叶节点(预剪枝)if self.use_pruning and self.prune_method == 'pre' and self.max_depth is not None and depth >= self.max_depth:return Node(is_leaf=True, label=self.majority_vote(y))# 如果样本数少于最小分裂样本数,创建叶节点(预剪枝)if self.use_pruning and self.prune_method == 'pre' and len(X) < self.min_samples_split:return Node(is_leaf=True, label=self.majority_vote(y))# 寻找最佳分裂点best_feature, best_threshold = self.find_best_split(X, y)# 如果无法找到有意义的分裂点,创建叶节点if best_feature is None:return Node(is_leaf=True, label=self.majority_vote(y))# 创建决策节点node = Node(feature=best_feature, threshold=best_threshold)# 根据最佳分裂点分割数据并递归构建子树if best_threshold is not None:  # 连续特征left_mask = X[:, best_feature] <= best_thresholdright_mask = X[:, best_feature] > best_threshold# 预剪枝:检查子节点样本数if self.use_pruning and self.prune_method == 'pre':if len(X[left_mask]) < self.min_samples_leaf or len(X[right_mask]) < self.min_samples_leaf:return Node(is_leaf=True, label=self.majority_vote(y))node.children['<='] = self.build_tree(X[left_mask], y[left_mask], depth + 1)node.children['>'] = self.build_tree(X[right_mask], y[right_mask], depth + 1)else:  # 离散特征unique_values = np.unique(X[:, best_feature])for value in unique_values:mask = X[:, best_feature] == valuesubset_X, subset_y = X[mask], y[mask]# 预剪枝:检查子节点样本数if self.use_pruning and self.prune_method == 'pre':if len(subset_X) < self.min_samples_leaf:continuenode.children[value] = self.build_tree(subset_X, subset_y, depth + 1)return nodedef fit(self, X, y):"""训练决策树"""self.root = self.build_tree(X, y)# 如果启用后剪枝if self.use_pruning and self.prune_method == 'post':self.prune_tree(X, y)def prune_tree(self, X, y):"""后剪枝函数,使用悲观错误剪枝法"""def _prune(node, X, y):if node.is_leaf:return node, len(y), np.sum(y == node.label)correct_predictions = 0total_samples = 0child_nodes = []# 递归剪枝子节点if node.threshold is not None:  # 连续特征left_mask = X[:, node.feature] <= node.thresholdright_mask = X[:, node.feature] > node.thresholdif len(X[left_mask]) > 0:node.children['<='], left_total, left_correct = _prune(node.children['<='], X[left_mask], y[left_mask])total_samples += left_totalcorrect_predictions += left_correctif len(X[right_mask]) > 0:node.children['>'], right_total, right_correct = _prune(node.children['>'], X[right_mask], y[right_mask])total_samples += right_totalcorrect_predictions += right_correctelse:  # 离散特征for value, child in node.children.items():mask = X[:, node.feature] == valueif np.any(mask):pruned_child, child_total, child_correct = _prune(child, X[mask], y[mask])node.children[value] = pruned_childtotal_samples += child_totalcorrect_predictions += child_correct

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

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

相关文章

Go 语言与 Tesseract 实现验证码自动解析

验证码(CAPTCHA)广泛用于网站和应用程序,以防止自动化脚本滥用系统。然而,在自动化测试和数据采集场景中,我们可能需要识别这些验证码。Tesseract 是一个开源 OCR(光学字符识别)引擎,能够解析图像中的文本信息…

Go 语言结合 Tesseract OCR 进行验证码识别

验证码(CAPTCHA)是一种常见的安全机制,主要用于防止自动化脚本的恶意操作。然而,在自动化测试、数据采集等合法需求下,我们可能需要自动解析验证码。本教程将介绍如何使用 Go 语言和 Tesseract OCR 解析验证码,并…

WordPress FindAll Membership插件身份验证绕过漏洞分析

本文详细分析了CVE-2025-13539漏洞,该漏洞影响FindAll Membership插件所有1.0.4及之前版本,攻击者可通过社交登录功能绕过身份验证,以管理员身份登录系统。概述 CVE-2025-13539是一个影响WordPress FindAll Members…

《程序员的修炼之道:从小工到专家》读后感一

书中关于 “代码维护” 的观点让我深受触动。它提到 “代码是写给未来的自己和同事看的”,这打破了我此前 “功能实现就行” 的片面认知。之前写代码时,为赶进度常忽略注释和代码结构,导致后期迭代时,自己都要花大…

we_will_rockyou

rockyou字典地址:https://gitlab.com/kalilinux/packages/wordlists/blob/kali/master/rockyou.txt.gz 下载文件,根据题目名称使用rockyou字典爆破打开文件获得flag

11.29(1)

补11.28 1.类图 ┌─────────────────┐ │ AbstractChatRoom │ ├─────────────────┤ │ +register() │ │ +sendText() │ │ +sendImage() │ └────────…

251129我的效率为何如此之低

是不是我关注和摄入的东西太多了,应该简单一些吧。 而且我好像,,,,不能沉下心来工作,就是总想选择一些安逸的东西。一会儿就想去看看别的,啊,死脑子快控制住自己啊啊!! 想尝试一下毛巾胶 最近老是退货,88vi…

20232324 2025-2026-2 《网络与系统攻防技术》实验八实验报告

20232324 2025-2026-2 《网络与系统攻防技术》实验八实验报告1.实验内容(1)Web前端HTML 能正常安装、启停Apache。理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML。 (2)Web前端javascipt理解Java…

11月第一篇笔记

书中对“代码复用”的解读彻底点醒了我:复用不是简单的复制粘贴,而是构建“可复用的知识模块”。作者提到,优秀的开发者会像搭建积木一样积累可复用组件,既节省时间又减少错误。这让我反思,要是实训前小组能先梳理…

C++自学之路1:Hello world

C++ 语法基础 本文主要通过Hello world这样一个简单的c++程序来认识C++的基础语法框架 本文内容主要来自OI wiki #include <iostream> // 引用头文件int main() // 定义 main 函数 { s…

《代码大全》读后感四

《代码大全 2》最让我惊喜的是它的实用性。书中没有空洞的理论,而是用大量真实案例讲解 “如何写出易读的代码”。比如它提到 “函数长度控制在 20 行内”,我试着在项目中实践,发现后续修改时,能快速定位核心逻辑;…

k8s 笔记

好的,我们来详细整理一下关于 Kubernetes Endpoints 资源的笔记。这份笔记将严格按照你的大纲,并力求概念通俗易懂、案例详尽、代码完整且包含输出解释。Kubernetes Endpoints 资源深度解析 一、什么是 Endpoints 资…

11月第二篇笔记

“在动手编码前,先确保理解了问题本身”,书中这句忠告,是我在数据库课程设计中用返工代价换来的深刻教训。当时课程要求开发一个图书借阅管理系统,我拿到需求文档后,看到“实现图书借阅、归还功能”就立刻投入编码…

《代码大全》读后感五

时隔三年再读《代码大全 2》,我有了新的感悟。初读时,我只关注书中的技巧方法,如今却读懂了它背后的 “匠心”—— 对代码质量的极致追求,对开发效率的深度思考。它让我明白,编程不只是谋生的技能,更是需要用心打…

网安学习day x 天

抓包课程笔记 抓包工具: Burpcharles fiddler 转发工具: proxifier学习了web/安卓模拟器/wx小程序/pc应用的抓包 proxifier 建立代理服务器 设置代理规则:基于进程筛选 继续IP或域名筛选 基于端口筛选 app应用 安装证…

关于synchronized-reentrantlock-volatile学习总结1.0

Synchronized synchronized 是什么 synchronized是 java 提供的原子性内置锁,实现基本的同步机制,不支持超时,非公平,不可中断,不支持多条件,基于 JVM 的 Monitor(监视锁)机制实现,主要解决的是多个线程之间的…

nginx:普通用户使用80端口启动nginx报错,nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

nginx:普通用户使用80端口启动nginx报错,nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)解释 在大多数Linux发行版中,端口80通常被配置为仅由root用户或具有相应权限的用户监听。 方式一:直接…

通过C语言实现文件加密和解密

这是一个很好的学习项目,希望有需要的小伙伴能从中获益。 一、核心思路 a2p1aDdmLmNvbQ== kjuh7f.coma2p1aDdmLmNvbQ== 文件加密的本质是:通过某种算法(加密算法)和密钥,将原始文件(明文)转换为不可读的乱码(密…

NOIP2025 赛后彻底自我反省

差不多把我打醒了。 100+20+0+0(极小概率T2 多eps分(没调完的代码)),不会是全校最低吧。 打的跟大便一样。 估计队线在200~240左右?场上历程 10分钟过了T1。 接下来开始看剩下三题,给我的感受是,T3神秘的树高…

易错点总结(含策略)

格式:出现的问题-导致的后果-改进方式 1.策略失误(总体问题)1.开题顺序问题 有时出现在模拟赛,正赛没有失误 后面得题目较为简单时候容易出现丢分问题 在每一次比赛前都提醒自己不要出现漏看题的问题2.无法正确评估…