基于C++的决策树C4.5机器学习算法(不调包)

目前玩机器学习的小伙伴,上来就是使用现有的sklearn机器学习包,写两行代码,调调参数就能跑起来,看似方便,实则有时不利于个人能力发展,要知道现在公司需要的算法工程师,不仅仅只是会调参(这种工作,入门几个月的人就可以干了),而是要深入底层,能优化代码,能自己搭。

本文章适合以下几类人:

1)初学者,了解机器学习的实现过程

2)想提升自己的代码能力

第一步:原理

     决策树可以被简单的看成是一些if 和else,其优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。其缺点:可能会产生过度匹配问题。决策树相关详细理论的博客,网上有很多,我就不重复啰嗦了

第二步:代码实现

#include <vector>
#include <set>
#include <map>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <math.h>using namespace std;/*******树的构造*******/
struct TreeNode {string            m_sAttribute;//节点名字int               m_iDeciNum;  //yes 数int               m_iUnDecinum; //no 数vector<TreeNode*> m_vChildren;
};TreeNode* CreateTreeNode(string value)
{TreeNode* pNode = new TreeNode();pNode->m_sAttribute = value;return pNode;
}bool FindNode(TreeNode* pRoot, std::string& item)
{if (pRoot->m_sAttribute == item)return true;bool found = false;vector<TreeNode*>::iterator i = pRoot->m_vChildren.begin();while (!found && i < pRoot->m_vChildren.end()){found = FindNode(*i, item);++i;}return found;
}void ConnectTreeNodes(TreeNode* pParent, TreeNode* pChild)
{if (pParent != NULL){pParent->m_vChildren.push_back(pChild);}
}void PrintTreeNode(TreeNode* pNode)
{if (pNode != NULL){printf("value of this node is: %d.\n", pNode->m_sAttribute);printf("its children is as the following:\n");std::vector<TreeNode*>::iterator i = pNode->m_vChildren.begin();while (i < pNode->m_vChildren.end()){if (*i != NULL)printf("%s\t", (*i)->m_sAttribute);++i;}printf("\n");}else{printf("this node is null.\n");}printf("\n");
}void PrintTree(TreeNode* pRoot)
{PrintTreeNode(pRoot);if (pRoot != NULL){std::vector<TreeNode*>::iterator i = pRoot->m_vChildren.begin();while (i < pRoot->m_vChildren.end()){PrintTree(*i);++i;}}
}void DestroyTree(TreeNode* pRoot)
{if (pRoot != NULL){std::vector<TreeNode*>::iterator i = pRoot->m_vChildren.begin();while (i < pRoot->m_vChildren.end()){DestroyTree(*i);++i;}delete pRoot;}
}
/*******树的构造*******/class DecisionTree {
private:struct attrItem{std::vector<int>  itemNum;  //itemNum[0] = itemLine.size()//itemNum[1] = decision numset<int>		  itemLine; //可用行};//重点struct attributes{string attriName; //属性名字vector<double> statResult;map<string, attrItem*> attriItem;//存放子目录的信息};vector<attributes*> statTree;int attriNum;vector<vector<string>> infos;map<string, int> attr_clum;//作用不大public:DecisionTree() {attriNum = 0;}vector<vector<string>>& getInfos(){return infos;}vector<attributes*>& getStatTree(){return statTree;}int pretreatment(string filename, set<int>& readLineNum, vector<int>& readClumNum);int statister(vector<vector<string>>& infos, vector<attributes*>& statTree,set<int>& readLine, vector<int>& readClumNum);int compuDecisiNote(vector<attributes*>& statTree, int deciNum, int lineNum, vector<int>& readClumNum);double info_D(int deciNum, int sum);void resetStatTree(vector<attributes*>& statTree, vector<int>& readClumNum);double Info_attr(map<string, attrItem*>& attriItem, double& splitInfo, int lineNum);void CreatTree(TreeNode* &treeHead, vector<attributes*>& statTree, vector<vector<string>>& infos,set<int>& readLine, vector<int>& readClumNum, int deep);
};/*
* @function CreatTree 预处理函数,负责读入数据,并生成信息矩阵和属性标记
* @param: filename 文件名
* @param: readLineNum 可使用行set
* @param: readClumNum 可用属性vector 0可用 1不可用
* @return int 返回函数执行状态
*/int DecisionTree::pretreatment(string filename, set<int>& readLineNum, vector<int>& readClumNum)
{}/*
* @function Info_attr info_D 总信息量
* @param: deciNum 有效信息数
* @param: sum 总信息量
* @return double 总信息量比例
*/
double DecisionTree::info_D(int deciNum, int sum)
{double pi = (double)deciNum / (double)sum;double result = 0.0;if ((1.0 - pi) < 0.000001 || (pi - 0.0) < 0.000001){return result;}result = pi * (log(pi) / log((double)2)) + (1 - pi)*(log(1 - pi) / log((double)2));return -result;
}/*
* @function Info_attr 总信息量
* @param: deciNum 有效信息数
* @param: sum 总信息量
* @return double
*/
double DecisionTree::Info_attr(map<string, attrItem*>& attriItem, double& splitInfo, int lineNum)
{double result = 0.0;for (map<string, attrItem*>::iterator item = attriItem.begin();item != attriItem.end();++item){double pi = (double)(item->second->itemNum[0]) / (double)lineNum;splitInfo += pi * (log(pi) / log((double)2));double sub_attr = info_D(item->second->itemNum[1], item->second->itemNum[0]);result += pi * sub_attr;}splitInfo = -splitInfo;return result;
}/*
* @function compuDecisiNote 计算C4.5
* @param: statTree 为状态树,此树动态更新,但是由于是DFS对数据更新,所以不必每次新建状态树
* @param: deciNum Yes的数据量
* @param: lineNum 计算set的行数
* @param: readClumNum 用于计算的set
* @return int 信息量最大的属性号
*/
int DecisionTree::compuDecisiNote(vector<attributes*>& statTree, int deciNum, int lineNum, vector<int>& readClumNum)
{double max_temp = 0;int max_attribute = 0;//总的yes行的信息量double infoD = info_D(deciNum, lineNum);for (int i = 0; i < attriNum - 1; i++){if (readClumNum[i] == 0){double splitInfo = 0.0;//infodouble info_temp = Info_attr(statTree[i]->attriItem, splitInfo, lineNum);statTree[i]->statResult.push_back(info_temp);//gaindouble gain_temp = infoD - info_temp;statTree[i]->statResult.push_back(gain_temp);//split_infostatTree[i]->statResult.push_back(splitInfo);//gain_infodouble temp = gain_temp / splitInfo;statTree[i]->statResult.push_back(temp);//得到最大值*/if (temp > max_temp){max_temp = temp;max_attribute = i;}}}return max_attribute;
}/*
* @function resetStatTree 清理状态树
* @param: statTree 状态树
* @param: readClumNum 需要清理的属性set
* @return void
*/void DecisionTree::resetStatTree(vector<attributes*>& statTree, vector<int>& readClumNum)
{for (int i = 0; i < readClumNum.size() - 1; i++){if (readClumNum[i] == 0){map<string, attrItem*>::iterator it_end = statTree[i]->attriItem.end();for (map<string, attrItem*>::iterator it = statTree[i]->attriItem.begin();it != it_end; it++){delete it->second;}statTree[i]->attriItem.clear();statTree[i]->statResult.clear();}}
}int main(int argc, char* argv[]) {string filename = "tree.txt";DecisionTree dt;int attr_node = 0;TreeNode* treeHead = nullptr;set<int> readLineNum;vector<int> readClumNum;int deep = 0;if (dt.pretreatment(filename, readLineNum, readClumNum) == 0){dt.CreatTree(treeHead, dt.getStatTree(), dt.getInfos(), readLineNum, readClumNum, deep);}return 0;
}

第三步:运行过程

IDE编译软件用vs2010以上版本,运行结果

10ca49f0ced0fb33295195f078c03e56.png

第四步:项目源码下载:

整套算法系列:深度学习与机器学习_AI洲抿嘴的薯片的博客-CSDN博客

项目源码下载地址:关注文末【AI街潜水的八角】,回复【决策树机器学习算法】即可下载

整套项目源码内容包含

程序里面包括决策树C4.5机器学习算法,接近上千行代码

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

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

相关文章

这款Chrome 插件,使浏览器页面快速滑动到最底部和最顶部,并且还能...

前言 前几日我在使用谷歌浏览器&#xff0c;也就是chrome的时候&#xff0c;浏览一个内容很长的页面&#xff0c;由于页面上的内容有前后关联&#xff0c;所以我必须不停地切换到上面和下面。这非常不方便。使我非常抓狂。后来&#xff0c;我灵机一动&#xff0c;去谷歌浏览器…

汉诺塔问题代码分享及思路分享(c基础)

可以先自己尝试&#xff0c;只要看见过递归即可写。&#xff08;我自己是&#xff09;希望能自己尝试出来。 两种方法迭代比递归快很多.(不发代码的原因是想让你自己动手) 1 递归 2 迭代 猜数游戏是自己写的第一个有互动的程序。对我很有意义。 我绑定资源了的&#xff0c;大…

第9章 Apache WEB服务器企业实战

万维网 (WORLD WIDE WEB,WWW)服务器,也称之为WEB服务器,主要功能是提供网上信息浏览服务。WWW是 Internet的多媒体信息查询工具,是Internet上飞快发展的服务,也是目前用的最广泛的服务。正是因为有了WWW软件,才使得近年来 Internet 迅速发展。 目前主流的WEB服务器软件包…

第10章 MYSQL服务器企业实战

MySQL是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 旗下公司。MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。 本章介绍关系型数据库特…

【初阶数据结构与算法】沉浸式刷题之顺序表练习(顺序表以及双指针两种方法)

文章目录 顺序表练习1.移除数组中指定的元素方法1&#xff08;顺序表&#xff09;方法2&#xff08;双指针&#xff09; 2.删除有序数组中的重复项方法1&#xff08;顺序表&#xff09;方法2&#xff08;双指针&#xff09; 3.双指针练习之合并两个有序数组方法1&#xff08;直…

【flask开启进程,前端内容图片化并转pdf-会议签到补充】

flask开启进程,前端内容图片化并转pdf-会议签到补充 flask及flask-socketio开启threading页面内容转图片转pdf流程前端主js代码内容转图片-browser端browser端的同步编程flask的主要功能route,def 总结 用到了pdf,来回数据转发和合成,担心flask卡顿,响应差,于是刚好看到threadi…

PADS的GND难解之谜——GND铺不上捅?GND焊盘上全是绿色叉号?

PADS难解之谜——GND覆不上铜&#xff1f;焊盘上全是叉号&#xff1f; 文章目录 PADS难解之谜——GND覆不上铜&#xff1f;焊盘上全是叉号&#xff1f;1、GND灌铜灌不上&#xff1f;2、GND焊盘上全是绿色叉号&#xff1f; 如果对你有帮助&#xff0c;就点赞收藏把&#xff01;(…

02- 模块化编程-007 Ltc1684( ADC16-Bit)采样显示

1、Ltc1684芯片介绍 该芯片是一款高精度的16位模数转换器(ADC)&#xff0c;适合于高精度仪器的开发&#xff0c;它能提供精准的模拟信号到数字信号的转换。 特性 采用 MSOP 封装的 16 位、250ksps ADC 单 5V 电源 低电源电流&#xff1a;850μA (典型值) 自动停机功能可把电源…

信息安全工程师(80)网络安全测评技术与工具

前言 网络安全测评是评估信息系统、网络和应用程序的安全性&#xff0c;以发现潜在的漏洞和威胁&#xff0c;并确保系统符合安全标准和政策的过程。 一、网络安全测评技术 渗透测试&#xff08;Penetration Testing&#xff09; 描述&#xff1a;通过模拟真实的攻击&#xff0c…

基于STM32的太阳跟踪系统设计

引言 本项目基于STM32微控制器设计了一个智能太阳跟踪系统&#xff0c;通过集成光敏传感器模块和电机控制系统&#xff0c;实现太阳能电池板的自动调节&#xff0c;以保持太阳能电池板始终垂直对准太阳&#xff0c;从而最大化光能的吸收效率。该系统通过实时监测太阳光的方向&…

新能源汽车与公共充电桩布局

近年来,全球范围内对新能源汽车产业的推动力度不断增强,中国新能源汽车市场也呈现蓬勃发展的势头,在政策与市场的共同推动下,新能源汽车销量持续增长。然而,据中国充电联盟数据显示,充电基础设施建设滞后于新能源汽车数量增长的现状导致充电桩供需不平衡,公共充电桩服务空白区域…

Qt中的Model与View 4:QStandardItemModel与QTableView

目录 QStandardItemModel API QTableView 导航 视觉外观 坐标系统 API 样例&#xff1a;解析一个表格txt文件 QStandardItemModel QStandardItemModel 可用作标准 Qt 数据类型的存储库。它是模型/视图类之一&#xff0c;是 Qt 模型/视图框架的一部分。它提供了一种基于…

【STM32】项目实战——OV7725/OV2604摄像头颜色识别检测(开源)

本篇文章分享关于如何使用STM32单片机对彩色摄像头&#xff08;OV7725/OV2604&#xff09;采集的图像数据进行分析处理&#xff0c;最后实现颜色的识别和检测。 目录 一、什么是颜色识别 1、图像采集识别的一些基本概念 1. 像素&#xff08;Pixel&#xff09; 2. 分辨率&am…

Request 和 Response 万字详解

文章目录 1.Request和Response的概述2.Request对象2.1 Request 继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式 2.3 解决post请求乱码问题 掌握内容讲解内容小结 2.4 Request请求转发 3.HTTP响应详…

经典网络模型

文章目录 网络演变过程1、阻塞IO&#xff08;BIO&#xff09;实现缺点 2、非阻塞IO&#xff08;NIO&#xff09;实现改进后设置非阻塞IO缺点 3、IO多路复用第一版&#xff08;select/poll&#xff09;问题点改进缺点 4、IO多路复用第二版&#xff08;epoll&#xff09;5、信号驱…

从神经元到神经网络:深度学习的进化之旅

神经元、神经网络 神经元 Neuron )&#xff0c;又名感知机( Perceptron )&#xff0c;在模型结构上与 逻辑回归 一致&#xff0c;这里以一个二维输入量的例子对其进行进一步 的解释&#xff1a; 假设模型的输 入向 量是一 维特征向 (x1,x2). 则单神 经元的模型结构 如下…

面试题:Spring(一)

1. Spring框架中bean是单例么&#xff1f; Service Scope("singleton") public class UserServiceImpl implements UserService { }singleton : bean在每个Spring IOC容器中只有一个实例。prototype&#xff1a;一个bean的定义可以有多个实例。 2. Spring框架中的…

qt QFileSystemModel详解

1、概述 QFileSystemModel是Qt框架中的一个关键类&#xff0c;它继承自QAbstractItemModel&#xff0c;专门用于在Qt应用程序中展示文件系统的数据。这个模型提供了一个方便的接口&#xff0c;使得开发者可以轻松地在应用程序中集成文件和目录的树形结构&#xff0c;并通过视图…

从0开始深度学习(26)——汇聚层/池化层

池化层通过减少特征图的尺寸来降低计算量和参数数量&#xff0c;同时增加模型的平移不变性和鲁棒性。汇聚层的主要优点之一是减轻卷积层对位置的过度敏感。 1 最大汇聚层、平均汇聚层 汇聚层和卷积核一样&#xff0c;是在输入图片上进行滑动计算&#xff0c;但是不同于卷积层的…

右旋圆极化散射后的stocks矢量 与T3矩阵的关系

T3矩阵如下 斯托克斯与T3的关系如下。 斯托克斯与T3均没有平均处理&#xff0c;即斯托克斯是完全极化波的&#xff08;一种琼斯矢量得到&#xff09;&#xff0c;T3是由一个散射矩阵得到&#xff0c;只有一个特征值。