百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

机器学习之分类回归树(python实现CART)

off999 2024-11-26 07:24 23 浏览 0 评论

机器学习之分类回归树(python实现CART)

之前有文章介绍过决策树(ID3)。简单回顾一下:ID3每次选取最佳特征来分割数据,这个最佳特征的判断原则是通过信息增益来实现的。按照某种特征切分数据后,该特征在以后切分数据集时就不再使用,因此存在切分过于迅速的问题。ID3算法还不能处理连续性特征。 下面简单介绍一下其他算法:

CART 分类回归树

CART是Classification And Regerssion Trees的缩写,既能处理分类任务也能做回归任务。

CART树的典型代表时二叉树,根据不同的条件将分类。

CART树构建算法 与ID3决策树的构建方法类似,直接给出CART树的构建过程。首先与ID3类似采用字典树的数据结构,包含以下4中元素:

  • 待切分的特征
  • 待切分的特征值
  • 右子树。当不再需要切分的时候,也可以是单个值
  • 左子树,类似右子树。

过程如下:

  1. 寻找最合适的分割特征
  2. 如果不能分割数据集,该数据集作为一个叶子节点。
  3. 对数据集进行二分割
  4. 对分割的数据集1重复1, 2,3 步,创建右子树。
  5. 对分割的数据集2重复1, 2,3 步,创建左子树。

明显的递归算法。

通过数据过滤的方式分割数据集,返回两个子集。

def splitDatas(rows, value, column):
 # 根据条件分离数据集(splitDatas by value, column)
 # return 2 part(list1, list2)
 list1 = []
 list2 = []
 if isinstance(value, int) or isinstance(value, float):
 for row in rows:
 if row[column] >= value:
 list1.append(row)
 else:
 list2.append(row)
 else:
 for row in rows:
 if row[column] == value:
 list1.append(row)
 else:
 list2.append(row)
 return list1, list2
复制代码

划分数据点

创建二进制决策树本质上就是递归划分输入空间的过程。

代码如下:

# gini()
def gini(rows):
 # 计算gini的值(Calculate GINI)
 length = len(rows)
 results = calculateDiffCount(rows)
 imp = 0.0
 for i in results:
 imp += results[i] / length * results[i] / length
 return 1 - imp
复制代码

构建树

def buildDecisionTree(rows, evaluationFunction=gini):
 # 递归建立决策树, 当gain=0,时停止回归
 # build decision tree bu recursive function
 # stop recursive function when gain = 0
 # return tree
 currentGain = evaluationFunction(rows)
 column_lenght = len(rows[0])
 rows_length = len(rows)
 best_gain = 0.0
 best_value = None
 best_set = None
 # choose the best gain
 for col in range(column_lenght - 1):
 col_value_set = set([x[col] for x in rows])
 for value in col_value_set:
 list1, list2 = splitDatas(rows, value, col)
 p = len(list1) / rows_length
 gain = currentGain - p * evaluationFunction(list1) - (1 - p) * evaluationFunction(list2)
 if gain > best_gain:
 best_gain = gain
 best_value = (col, value)
 best_set = (list1, list2)
 dcY = {'impurity': '%.3f' % currentGain, 'sample': '%d' % rows_length}
 #
 # stop or not stop
 if best_gain > 0:
 trueBranch = buildDecisionTree(best_set[0], evaluationFunction)
 falseBranch = buildDecisionTree(best_set[1], evaluationFunction)
 return Tree(col=best_value[0], value = best_value[1], trueBranch = trueBranch, falseBranch=falseBranch, summary=dcY)
 else:
 return Tree(results=calculateDiffCount(rows), summary=dcY, data=rows)
复制代码

上面代码的功能是先找到数据集切分的最佳位置和分割数据集。之后通过递归构建出上面图片的整棵树。

剪枝

在决策树的学习中,有时会造成决策树分支过多,这是就需要去掉一些分支,降低过度拟合。通过决策树的复杂度来避免过度拟合的过程称为剪枝。 后剪枝需要从训练集生成一棵完整的决策树,然后自底向上对非叶子节点进行考察。利用测试集判断是否将该节点对应的子树替换成叶节点。 代码如下:

def prune(tree, miniGain, evaluationFunction=gini):
 # 剪枝 when gain < mini Gain, 合并(merge the trueBranch and falseBranch)
 if tree.trueBranch.results == None:
 prune(tree.trueBranch, miniGain, evaluationFunction)
 if tree.falseBranch.results == None:
 prune(tree.falseBranch, miniGain, evaluationFunction)
 if tree.trueBranch.results != None and tree.falseBranch.results != None:
 len1 = len(tree.trueBranch.data)
 len2 = len(tree.falseBranch.data)
 len3 = len(tree.trueBranch.data + tree.falseBranch.data)
 p = float(len1) / (len1 + len2)
 gain = evaluationFunction(tree.trueBranch.data + tree.falseBranch.data) - p * evaluationFunction(tree.trueBranch.data) - (1 - p) * evaluationFunction(tree.falseBranch.data)
 if gain < miniGain:
 tree.data = tree.trueBranch.data + tree.falseBranch.data
 tree.results = calculateDiffCount(tree.data)
 tree.trueBranch = None
 tree.falseBranch = None
复制代码

当节点的gain小于给定的 mini Gain时则合并这两个节点.。

最后是构建树的代码:

if __name__ == '__main__':
 dataSet = loadCSV()
 decisionTree = buildDecisionTree(dataSet, evaluationFunction=gini)
 prune(decisionTree, 0.4)
 test_data = [5.9,3,4.2,1.5]
 r = classify(test_data, decisionTree)
 print(r)
复制代码

可以打印decisionTree可以构建出如如上的图片中的决策树。 后面找一组数据测试看能否得到正确的分类。

完整代码和数据集请查看:

github:CART

总结:

  • CART决策树
  • 分割数据集
  • 递归创建树

参考文章:

CART分类回归树分析与python实现

CART决策树(Decision Tree)的Python源码实现

相关推荐

apisix动态修改路由的原理_动态路由协议rip的配置

ApacheAPISIX能够实现动态修改路由(DynamicRouting)的核心原理,是它将传统的静态Nginx配置彻底解耦,通过中心化配置存储(如etcd)+OpenRest...

使用 Docker 部署 OpenResty Manager 搭建可视化反向代理系统

在之前的文章中,xiaoz推荐过可视化Nginx反向代理工具NginxProxyManager,最近xiaoz还发现一款功能更加强大,界面更加漂亮的OpenRestyManager,完全可以替代...

OpenResty 入门指南:从基础到动态路由实战

一、引言1.1OpenResty简介OpenResty是一款基于Nginx的高性能Web平台,通过集成Lua脚本和丰富的模块,将Nginx从静态反向代理转变为可动态编程的应用平台...

OpenResty 的 Lua 动态能力_openresty 动态upstream

OpenResty的Lua动态能力是其最核心的优势,它将LuaJIT嵌入到Nginx的每一个请求处理阶段,使得开发者可以用Lua脚本动态控制请求的生命周期,而无需重新编译或rel...

LVS和Nginx_lvs和nginx的区别

LVS(LinuxVirtualServer)和Nginx都是常用的负载均衡解决方案,广泛应用于大型网站和分布式系统中,以提高系统的性能、可用性和可扩展性。一、基本概念1.LVS(Linux...

外网连接到内网服务器需要端口映射吗,如何操作?

外网访问内网服务器通常需要端口映射(或内网穿透),这是跨越公网与私网边界的关键技术。操作方式取决于网络环境,以下分场景详解。一、端口映射的核心原理内网服务器位于私有IP地址段(如192.168.x.x...

Nginx如何解决C10K问题(1万个并发连接)?

关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。Nginx是大型架构的必备中间件,下面我就全面来详解NginxC10k问题@mikechen文章来源:mikec...

炸场!Spring Boot 9 大内置过滤器实战手册:从坑到神

炸场!SpringBoot9大内置过滤器实战手册:从坑到神在Java开发圈摸爬滚打十年,见过太多团队重复造轮子——明明SpringBoot自带的过滤器就能解决的问题,偏偏要手写几十...

WordPress和Typecho xmlrpc漏洞_wordpress主题漏洞

一般大家都关注WordPress,毕竟用户量巨大,而国内的Typecho作为轻量级的博客系统就关注的人并不多。Typecho有很多借鉴WordPress的,包括兼容的xmlrpc接口,而WordPre...

Linux Shell 入门教程(六):重定向、管道与命令替换

在前几篇中,我们学习了函数、流程控制等Shell编程的基础内容。现在我们来探索更高级的功能:如何控制数据流向、将命令链接在一起、让命令间通信变得可能。一、输入输出重定向(>、>>...

Nginx的location匹配规则,90%的人都没完全搞懂,一张图让你秒懂

刚配完nginx网站就崩了?运维和开发都头疼的location匹配规则优先级,弄错顺序直接导致500错误。核心在于nginx处理location时顺序严格:先精确匹配=,然后前缀匹配^~,接着按顺序正...

liunx服务器查看故障命令有那些?_linux查看服务器性能命令

在Linux服务器上排查故障时,需要使用一系列命令来检查系统状态、日志文件、资源利用情况以及网络状况。以下是常用的故障排查命令,按照不同场景分类说明。1.系统资源相关命令1.1查看CPU使...

服务器被入侵的常见迹象有哪些?_服务器入侵可以被完全操纵吗

服务器被入侵可能会导致数据泄露、服务异常或完全失控。及时发现入侵迹象能够帮助你尽早采取措施,减少损失。以下是服务器被入侵的常见迹象以及相关的分析与处理建议。1.服务器被入侵的常见迹象1.1系统性能...

前端错误可观测最佳实践_前端错误提示

场景解析对于前端项目,生产环境的代码通常经过压缩、混淆和打包处理,当代码在运行过程中产生错误时,通常难以还原原始代码从而定位问题,对于深度混淆尤其如此,因此Mozilla自2011年开始发起并...

8个能让你的Kubernetes集群“瞬间崩溃”的配置错误

错误一:livenessProbe探针“自杀式”配置——30秒内让Pod重启20次现象:Pod状态在Running→Terminating→CrashLoopBackOff之间循环,重启间隔仅...

取消回复欢迎 发表评论: