剪枝、cart树

article/2025/9/24 16:25:00

一、剪枝

1. 为什么要剪枝

在决策树生成的时候,更多考虑的是训练数据,而不是未知数据,这会导致过拟合,使树过于复杂,对于未知的样本不准确。

2. 剪枝的依据——通过极小化决策树的损失函数

定义:
设树的叶节点个数为,
是树的叶节点,该叶节点有个样本,
其中属于类的样本点有个,
是叶节点的经验熵
是超参数

损失函数的定义为:
在这里插入图片描述
经验熵为:
在这里插入图片描述
代入简化:

令:
在这里插入图片描述
则:
在这里插入图片描述

α的作用:

  • 控制着预测误差和树复杂度之间的平衡
  • α大,促使选择更为简单的树
  • α小,选择更为复杂的树
  • α = 0, 只考虑模型与训练数据的拟合程度,不考虑复杂度

3. 剪枝算法

输入:未剪枝的决策树T,超参数
输出: 修剪好的树
(1)计算每个叶节点的经验熵。
(2)递归的从树的叶节点向上回溯。 设一组叶节点回溯到其父节点之前和之后的整体树分别为在这里插入图片描述在这里插入图片描述,若他们的损失函数:
在这里插入图片描述
即若修剪后的子树的损失函数比原来更小,则进行剪枝,将父节点作为新的叶节点。
(3)返回(2),知道不能继续进行,得到损失函数最小的子树在这里插入图片描述

二、基尼指数

分类过程中,假设有K个类,样本点属于第k个类的概率为Pk,则概率分布的基尼指数定义为:
在这里插入图片描述

对于二分类的问题,若k=1时,概率是p,k=2时,概率是(1-p),则:
在这里插入图片描述

对于给定的样本集合D,其基尼指数为:
在这里插入图片描述

三、CART树

CART树全称是 classification and regression tree,既可以分类(离散数据),也可以用于回归(连续数据)。

3.1 回归树

如果目标是连续变量,则是Regression Tree回归树。CART树是二叉树,不像多叉树那样形成过多的数据碎片。
对于连续变量X(x1…xn)如何处理?
首先将值排序,分别取其两相邻值的平均值点作为分隔点,将树一分成左枝和右枝,不断扫描,进而判断最佳分割点。特征值小于分裂值就走左子树,或者就走右子树。

下面从数学层面做推导:
假设X与Y分别为输入和输出变量,并且Y是连续变量,给定训练数据集:
在这里插入图片描述

考虑如何生成回归树。
一个回归树对用着一个特征空间的一个划分及在划分单元上的是输出值。假设已输入特征空间划分为M个单元R1,R2…Rm,并且在每个单元上有一个固定的输出类别Cm,于是我们把回归树表示为:
在这里插入图片描述

损失函数:
在这里插入图片描述

表示回归树对于训练数据的预测误差,用平方误差最小的准则求解每个单元上的最优输出值。我们考虑特征空间的第m个单元上的的最优值,它是上的所有输入实例对应输出的的均值:(连续值通常的最优值都是取均值)
在这里插入图片描述

问题是怎么样对输入空间进行划分,我们采用启发式的方法;选择第j个变量和它取的值s,作为切分变量(splitting variable)和切分点(splitting point),并定义两个区域:
在这里插入图片描述

然后我们需要寻求切分变量j和最有优切分点s,求解如下方程:
在这里插入图片描述

对固定输入变量j可以寻找最优切分点s:
在这里插入图片描述

遍历所有的输入变量,找到最优的切分变量j,构成一个对(j,s),依次将输入空间划分为两个区域。
接着对每个区域重复上述过程,直到满足停止条件为主。这样就生成了一颗回归树,也称为最小二乘回归树(least square regression tree)。
为什么是平均值?
均方误差的目标函数最优值(取定值)是均值
在这里插入图片描述

3.2.1 分类树

如果数据集D根据特征A在某一取值a上进行分割,得到D1,D2两部分后,那么在特征A下集合D的基尼系数如下所示。
在这里插入图片描述

其中基尼系数Gini(D)表示集合D的不确定性,基尼系数Gini(D,A)表示A=a分割后集合D的不确定性。基尼指数越大,样本集合的不确定性越大。这一点与熵相似。

对于属性A,分别计算任意属性值将数据集划分为两部分之后的Gini,选取其中的最小值,作为属性A得到的最优二分方案。然后对于训练集S,计算所有属性的最优二分方案,选取其中的最小值,作为样本及S的最优二分方案。
在这里插入图片描述

3.2.2 分类树原理

如果目标变量是离散变量,则是classfication Tree分类树。
分类树是使用树结构算法将数据分成离散类的方法。
(1) 分类树两个关键点:
将训练样本进行递归地划分自变量空间进行建树
用验证数据进行剪枝。
(2)对于离散变量X(x1…xn)处理:
分别取X变量各值的不同组合,将其分到树的左枝或右枝,并对不同组合而产生的树,进行评判,找出最佳组合。如果只有两个取值,直接根据这两个值就可以划分树。取值多于两个的情况就复杂一些了,如变量年纪,其值有“少年”、“中年”、“老年”,则分别生产{少年,中年}和{老年},{上年、老年}和{中年},{中年,老年}和{少年},这三种组合,最后评判对目标区分最佳的组合。因为CART二分的特性,当训练数据具有两个以上的类别,CART需考虑将目标类别合并成两个超类别,这个过程称为双化。这里可以说一个公式,n个属性,可以分出(2^n-2)/2种情况。

3.2.3 分类树算法步骤

CART分类树生成算法:
输入:训练数据集D,停止计算的条件;
输出:CART决策树

根据训练数据集,从根节点开始,递归地对每个节点进行以下操作,构建二叉决策树:
(1)设结点的训练数据集为D,计算现有特征对该数据集的基尼指数,此时对每一个特征A,对其可能取得每个值a,根据样本点对A=a的测试为“是”或“否”将D分割成D1和D2两部分,利用集合的基尼指数公式计算A=a的基尼指数。
在这里插入图片描述
(2)在所有可能的特征A(切分变量)以及他们的所有可能的切分点a中,选择基尼指数最小的特征及其对应的切分点作为最优特征与最优切分点。依照最优特征和最优切分点,从现结点生成两个子节点,将训练数据集依特征分配到两个子节点中去。
(3)对两个子节点递归地调用(1),(2),直到满足停止条件。
(4)生成CART决策树。

3.2.4 案例

在这里插入图片描述

应用上述数据集,应用CART算法生成决策树。
分析:首先计算各特征的基尼指数,选择最优特征以及其最优切分点。我们以A1,A2,A3,A4表示年龄、有工作、有自己的房子和信贷4个特征,并以1,2,3表示年龄的值为青年、中年、老年,以1、2表示有工作和有自己的房子的值为是和否,以1、2、3表示信贷情况的值为非常好、好和一般。
求特征A1的基尼指数:
在这里插入图片描述

优于Gini(D,A1=1)和Gini(D,A1=3)相等,且最小,所以A1=1和A1=3都可以选作最优切分点。
求特征A2和A3的基尼指数:
在这里插入图片描述

由于A2和A3只有一个切分点,所以他们就是最优切分点。
求解特征4的基尼指数:
在这里插入图片描述

Gini(D,A4=3)最小,所以A4=3为A4的最优切分点。
在A1,A2,A3,A4几个特征中,Gini(D,A3=1)=0.27最小,所以选择A3为最优特征,A3=1为其最优切分点。于是根节点生成两个子节点,一个是叶节点,对另一个结点继续使用以上方法在A1,A2,A3中选择最优特征及其最优切分点,结果是A2=1,依次计算得知,所有结点都是叶节点。
该例子按照CART算法和ID3算法生成的决策树完全一致的。下图我们只拿A3和A2作为最优划分来切分数据集。
在这里插入图片描述

4、Cart树总结

创建分类树递归过程中,CART每次都选择当前数据集中具有最小Gini信息增益的特征作为结点划分决策树。ID3算法和C4.5算法虽然在对训练样本集的学习中可以尽可能多地挖掘信息,但其生成的决策树分支多、规模较大,CART算法的二分法可以简化决策树的规模(叶子结点个数),提高生成决策树的效率。对于连续特征,CART也是采取和C4.5同样的方法处理。为了避免过拟合(Overfitting),CART决策树需要剪枝(后剪枝)。预测过程当然也就十分简单,根据产生的决策树模型,延伸匹配特征值到最后的叶子节点即得到预测的类别。


http://chatgpt.dhexx.cn/article/GC4Cj8k7.shtml

相关文章

【机器学习】决策树——CART分类回归树(理论+图解+公式)

🌠 『精品学习专栏导航帖』 🐳最适合入门的100个深度学习实战项目🐳🐙【PyTorch深度学习项目实战100例目录】项目详解 数据集 完整源码🐙🐶【机器学习入门项目10例目录】项目详解 数据集 完整源码&…

CART树(分类回归树)

主要内容 (1)CART树简介 (2)CART树节点分裂规则 (3)剪枝 --------------------------------------------------------------------------------------------------------------------- 一、简介 CART…

CART树

算法概述 CART(Classification And Regression Tree)算法是一种决策树分类方法。 它采用一种二分递归分割的技术,分割方法采用基于最小距离的基尼指数估计函数,将当前的样本集分为两个子样本集,使得生成的的每个非叶子节点都有两个分支。因此…

Pytorch之view,reshape,resize函数

对于深度学习中的一下数据,我们通常是要变成tensor格式,并且需要对其调整形状,很多时候我们往往只关注view之后的结果(比如输出的尺寸),而不关心过程。但有时候还是要关注一下这个到底是怎么变换过来的&…

OpenCV-Python图像处理:插值方法及使用resize函数进行图像缩放

☞ ░ 前往老猿Python博客 https://blog.csdn.net/LaoYuanPython ░ 图像缩放用于对图像进行缩小或扩大,当图像缩小时需要对输入图像重采样去掉部分像素,当图像扩大时需要在输入图像中根据算法生成部分像素,二者都会利用插值算法来实现。 一…

vector的resize函数和reserve函数

博客原文:C基础篇 -- vector的resize函数和reserve函数_VampirEM_Chosen_One的博客-CSDN博客,写的特别好,谢谢原博主。 正文: 对于C的vector容器模板类,存在size和capacity这样两个概念,可以分别通过vect…

OpenCV 图片尺寸缩放——resize函数

文章目录 OpenCV中的缩放:resize函数代码案例 OpenCV中的缩放: 如果要放大或缩小图片的尺寸,可以使用OpenCV提供的两种方法: resize函数,是最直接的方式;pyrUp,pyrDown函数,即图像…

OpenCV的resize函数优化

背景 在使用OpenCV做图像处理的时候,最常见的问题是c版本性能不足,以resize函数为例来说明,将size为[864,1323,3]的函数缩小一半: Mat img0;gettimeofday(&t4, NULL);cv::resize(source, img0, cv::Size(cols_out,rows_out)…

C++ | resize函数的用法

最近在leetcode用C刷题,刚遇到一题需要给重新弄一个容器,并给容器初始化。新建容器要在private类中声明resize函数用来初始化preSum容器。 resize函数是C中序列式容器的一个共性函数,vv.resize(int n,element)表示调整容器vv的大小为n&#x…

opencv的resize函数

一、Opencv官方文档中resize的描述: resize Resizes an image. C: void resize(InputArray src, OutputArray dst, Size dsize, double fx0, double fy0, int interpolationINTER_LINEAR ) Python: cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) …

resize()函数

resize(),设置大小(size); reserve(),设置容量(capacity); size()是分配容器的内存大小,而capacity()只是设置容器容量大小,但并没有真正分配内存。 打个比方:正在建造…

OpenCV 图像缩放:cv.resize() 函数详解

目录 系列前言API函数详解参数列表缩放方式其一缩放方式其二两种方式的优先级关于插值方式 扩展 —— 相关函数 系列前言 这个系列是我第一个想要更下去的系列。每篇会全面介绍一个 OpenCV 函数,会给出 API 和示例。示例主要是用 Python 去写,但是 Open…

安卓中的几种线程间通信方式

一:Handler实现线程间的通信 andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。 在Android,这里的…

Java中的线程通信的几种方式

Java中的线程间通信是指不同线程之间相互协作,以完成一些复杂的任务或实现某些功能的过程。线程间通信主要包括两个方面:线程之间的互斥和同步,以及线程之间的数据共享和通信。Java提供了多种方式来实现线程间通信,本文将介绍Java…

创建线程的四种方式 线程通信

文章目录 1.1 创建线程1.1.1 创建线程的四种方式1.1.2 Thread类与Runnable接口的比较1.1.3 Callable、Future与FutureTask 1.2 线程组和线程优先级1.3 Java线程的状态及主要转化方法1.4 Java线程间的通信1.4.1 等待/通知机制1.4.2 信号量1.4.3 管道 1.1 创建线程 1.1.1 创建线…

【多线程间几种通信方式】

一、使用 volatile 关键字 基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想。大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式 代码案例 package com.han…

线程之间的通信方式

前言 我只是个搬运工,尊重原作者的劳动成果,本文来源下列文章链接: https://zhuanlan.zhihu.com/p/129374075 https://blog.csdn.net/jisuanji12306/article/details/86363390 线程之间为什么要通信? 通信的目的是为了更好的协…

Java线程间的通信方式

文章目录 线程间通信的定义一、等待—通知(1)等待—通知机制的相关方法:(2)注意事项:(4)notify()方法的核心原理(5)等待—通知机制的经典范式(6&a…

线程间实现通信的几种方式

目录 线程通信相关概述提出问题方式一:使用Object类的wait() 和 notify() 方法方式二:Lock 接口中的 newContition() 方法返回 Condition 对象,Condition 类也可以实现等待/通知模式方法三:使用 volatile 关键字方法四&#xff1a…

线程间的通信方式

对共享数据进行更改的时候,先到主内存中拷贝一份到本地内存中,然后进行数据的更改,再重新将数据刷到主内存,这中间的过程,其他线程是看不到的。 1、为什么需要线程通信 线程是操作系统调度的最小单位,有自…