结合rpart包的决策树介绍

决策树与CART算法

决策树是一种基于树状结构的监督学习算法。它通过从根节点开始递归地对特征进行划分,构建出一棵树来进行决策。决策树的构建过程需要解决的重要问题有三个:如何选择自变量、如何选择分割点、确定停止划分的条件。解决这些问题是希望随着划分过程的不断进行,决策树的分支节点所包含的样本尽可能属于同一类别,即节点的”纯度“(purity)越来越高。传统决策树算法包括ID3、C4.5和CART,主要的区别就是决策树生成的划分过程中选择的目标函数不同,ID3使用的是信息增益,C4.5使用信息增益率,CART使用的是Gini系数。相比于ID3和C4.5算法,CART算法处理连续型特征能力强、不受特征取值个数影响、非参数化、可剪枝,在解决各种类型的问题时更加灵活和有效。

rpart包提供了实现CART算法的功能,并允许在构建树的过程中进行剪枝,避免过拟合问题。使用rpart包,可以根据给定的训练数据集自动生成决策树模型,并使用该模型进行预测。本文会首先对CART算法原理进行简单介绍,再对rpart包中的主要函数进行介绍,最后利用实例看如何使用rpart包构建决策树模型。

CART模型介绍

CART树的构建过程是递归的,它通过反复选择最佳的特征进行节点分裂,直到满足停止条件为止。在每次分裂时,CART算法会选择最佳的特征和最佳的切分点,以最小化切分后的不纯度(分类问题)或者最小化切分后的均方误差(回归问题),CART使用的是基尼指数来衡量数据的不纯度。

基尼指数

假设有K个类别,第k个类别的概率为 p k p_{k} pk,数据集D的纯度可以用基尼值来度量:

G i n i ( D ) = ∑ k = 1 K p k ( 1 − p k ) = 1 − ∑ k = 1 K p k 2 Gini(D)=\sum_{k=1}^Kp_{k}(1-p_{k})=1-\sum_{k=1}^Kp_{k}^2 Gini(D)=k=1Kpk(1pk)=1k=1Kpk2

直观来说,Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率。因而,基尼值越小,数据集D的纯度越高。

属性a的基尼指数定义为:

G i n i _ i n d e x ( D , a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ G i n i ( D v ) Gini\_index(D,a)=\sum_{v=1}^V\frac{\left| D_{v} \right|}{\left| D\right|}Gini(D^{v}) Gini_index(D,a)=v=1VDDvGini(Dv)

于是在候选属性集合A中,选择使划分后的基尼指数最小的属性作为最优划分属性,即

a ∗ = a r g m i n a ∈ A G i n i _ i n d e x ( D , a ) a_{*}= \mathop{argmin}\limits_{a\in A}\quad Gini\_index(D,a) a=aAargminGini_index(D,a)

过拟合处理

由于决策树算法在学习的过程中为了尽可能的正确的分类训练样本,不停地对结点进行划分,因此这会导致整棵树的分支过多,也就容易导致了过拟合。剪枝是决策树学习算法对付“过拟合”的主要手段,决策树剪枝的基本策略有“预剪枝”和“后剪枝”。

  • 预剪枝(pre-pruning):在构建决策树过程时,提前停止。预剪枝就是在构造决策树的过程中,先对每个结点在划分前进行估计,若果当前结点的划分不能带来决策树模型泛华性能的提升,则不对当前结点进行划分并且将当前结点标记为叶结点。
  • 后剪枝(post-pruning):决策树构建完毕后,然后开始剪枝。先把整颗决策树构造完毕,然后自底向上的对非叶结点进行考察,若将该结点对应的子树换为叶结点能够带来泛华性能的提升,则把该子树替换为叶结点。

CART分类树算法具体流程

CART分类树算法有剪枝算法流程,算法输入训练集D,基尼系数的阈值,样本个数阈值,输出的是决策树T。算法从根节点开始,用训练集递归建立CART分类树。

  1. 对于当前节点的数据集为 D,如果样本个数小于阈值或没有特征,则返回决策子树,当前节点停止递归。
  2. 计算样本集 D 的基尼系数,如果基尼系数小于阈值,则返回决策树子树,当前节点停止递归。
  3. 计算当前节点现有的各个特征的各个特征值对数据集 D 的基尼系数,对于离散值和连续值的处理方法和基尼系数的计算见第二节。缺失值的处理方法和 C4.5 算法里描述的相同。
  4. 在计算出来的各个特征的各个特征值对数据集 D 的基尼系数中,选择基尼系数最小的特征A和对应的特征值a。根据这个最优特征和最优特征值,把数据集划分成两部分D1和 D2,同时建立当前节点的左右节点,做节点的数据集 D 为 D1,右节点的数据集 D 为 D2。
  5. 对左右的子节点递归的调用 1-4 步,生成决策树。

对生成的决策树做预测的时候,假如测试集里的样本 A 落到了某个叶子节点,而节点里有多个训练样本。则对于 A 的类别预测采用的是这个叶子节点里概率最大的类别。

主要函数介绍

rpart包提供的函数主要用于递归分区和剪枝,其中主要函数包括:

  • rpart():递归地构建一棵决策树。
  • printcp():打印交叉验证结果,显示在不同复杂度下测试误差率和复杂度参数的关系。
  • prune():根据不同的剪枝方法,来选择最优的剪枝点,并返回剪枝后的决策树。
  • predict():使用训练好的树模型对新数据进行预测。

其他函数为用于输出上述主要函数的结果和决策树绘制等辅助函数,此处不做详细说明。

函数rpart()

rpart()函数根据给定的训练数据集和参数来递归地构建决策树模型,函数的基本形式如下:

rpart(formula, data, weights, subset, na.action = na.rpart, method, model = FALSE, x = FALSE, y = TRUE, parms, control, cost, ...)
## rpart()函数参数介绍

- **formula**: 回归方程的形式,例如 `y ~ x1 + x2 + x3`
- **data**: 数据框形式的数据,包含前面的 `formula` 方程中的数据
- **weights**: 可选大小写权重
- **subset**: 可选表达式,表示在拟合中只应使用数据行的子集
- **na.action**: 缺失数据的处理办法,默认操作删除所有缺少因变量的观测值,但保留自变量缺失的观测值
- **method**: 利用树的末端数据类型来选择相应的变量分割方法,它影响了决策树中拆分变量和拆分点的选择方式

本参数有四种模型类型来指定用于构建决策树的特定类型:

  • “class”: 用于分类问题,响应变量是离散型。
  • “anova”: 用于回归问题,使用F检验选择最佳的连续型变量和拆分点。
  • “exp”: 用于回归问题,适用于指数分布响应变量,使用最小二乘法拟合模型。
  • “poisson”: 用于回归问题,适用于泊松分布响应变量,使用最小二乘法拟合模型。

x: 在结果中保留 x 矩阵的副本
y: 在结果中保留因变量的副本。如果缺少并且提供了模型,则默认为 FALSE
parms: 用来设置三个参数:先验概率、损失矩阵、分类纯度的度量方法
control: 对树进行一些设置,控制每个节点上的最小样本量、交叉验证次数、复杂性度量即 cp 值等对树的一些设置

```r
 rpart.control(minsplit=20, minbucket=round(minsplit/3), cp=0.01, maxcompete=4, maxsurrogate=5, usesurrogate=2, xval=10, surrogatestyle=0, maxdepth=30, ...)
rpart.control中参数介绍:
- minsplit: 在进行拆分之前,节点中的观察数必须达到最小要求。
- minbucket:叶子节点最小样本数
- cp(complexity parameter): 指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度
- maxcompete:指定保留在输出中的竞争拆分数量
- maxsurrogate:指定保留在输出中的替代拆分数量
- usesurrogate:指定是否使用替代拆分
- maxdepth:树的深度
- xval: 交叉验证次数
  • cost: 损失矩阵,在剪枝的时候,叶子节点的加权误差与父节点的误差进行比较,考虑损失矩阵的时候,从将“减少-误差”调整为“减少-损失”

输出信息

rpart()函数的输出信息包含了决策树模型的相关信息,可以通过使用print()函数或者summary()函数查看,具体包含:

  • node: 节点的编号,每个节点都有唯一的编号,编号从1开始,一直到叶子节点的数量为止
  • split: 该节点选用的切分变量和切分点,即表示样本划分的规则
  • n: 该节点的样本数量
  • loss: 该节点的损失函数。通常是基于选定的损失函数衡量预测误差的指标
  • yval: 该节点的预测值 (或类别)。对于回归模型,预测值为该节点所有样本目标变量的平均值;对于分类模型,预测值为该节点样本中数量最多的类别
  • yprob: 各个类别的概率。它只在决策树用于分类问题时有意义,表示在该节点下,各个类别的比例
  • *: 代表该节点是叶子节点,不再分裂

函数prune()

prune()函数对决策树进行剪枝,函数的基本形式如下:

prune(tree, cp, ...)

prune()函数参数介绍

  • tree: 一个回归树对象,常是rpart()的结果对象
  • cp: 复杂性参数(complex parameter),指剪枝采用的阈值。指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度,用来节省剪枝浪费的不必要的时间。

输出信息

prune()函数的输出信息包含了剪枝后的决策树模型的相关信息,同样可通过使用print()函数或summary()函数查看,参数含义同rpart()函数输出参数,此处不再进行赘述。

predict()

利用拟合好的决策树对象来预测响应向量,其基本形式为:

predict(object, newdata, type = c("vector", "prob", "class", "matrix"), na.action = na.pass, ...)

predict()函数参数介绍

  • object: 类“rpart”的拟合模型对象,即是拟合好的决策树

  • newdata: 需要进行预测的值的数据框,是对于树模型定义的每一个变量的取值。该变量可以是数值型,分类型或逻辑型,并且必须与一开始用于训练模型时的变量/因子相同

  • type: 预测结果的类型,可选参数如下,默认"default",意味着返回与此前拟合树模型的类型相同的结果。

    type中可选参数:
    - vector: 返回连续型或类别型变量的预测值/分类
    - prob: 返回类别型变量的预测概率
    - class: 返回每个新观察的分类预测
    - matrix: 返回每个新观察的所有分类预测和概率
    
  • na.action: 指定处理缺失值的方式,默认是na.pass,即不处理缺失值。

输出信息

predict()函数返回的值,即是其type参数所指定的,默认返回与之前拟合树模型的类型相同的结果,一般来说,连续型预测值是新观察变量的数值预测,类别型预测是对新观察变量的分类预测。概率值表示每个类别的相对可能性。

实战案例

此部分通过具体的示例演示如何使用rpart包中函数构建决策树,分别介绍了分类树和回归树两种类型模型的应用案例,并在构建模型时使用了不同的剪枝方法。

分类树实例

此分类树实例利用rpart包中自带的kyphosis数据集,它包括81个接受脊柱矫正手术的儿童的数据,预测变量是Kyphosis(术后是否存在后凸(一种变形)的因素,为分类数据),预测变量是Age(年龄(以月记))、Number(涉及的椎骨数目)和Start(第一椎体手术数)。为了防止过拟合,该分类树有预剪枝操作。R语言代码操作如下:

# 载入数据
data(kyphosis)
#分类树构建
fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis,
             parms = list(prior = c(0.65, 0.35), split = "gini"),
             control = rpart.control(cp = 0.05))
# 查看决策树的具体信息
print(fit)
rpart.plot(fit)
# 预测
newdata <- data.frame(Age = 10, Number = 1, Start = 3)
predict(fit, newdata = newdata)

在上面的分类树构建的过程中,parms参数指定两个类别Kyphosis="absent"和Kyphosis="present"的先验概率,设定Kyphosis="absent"和Kyphosis="present"的先验概率分别为0.65和0.35;split参数指定使用Gini系数作为衡量节点分裂能力的指标,control参数指定了树的复杂程度,如果初始cp值为0,则没有预剪枝操作。

接着使用print函数查看拟合树模型的细节信息,split表示样本划分的规则,n代表样本大小,loss为分类错误的代价,yval为分类结果,yprob为两类的百分比,*表示叶子节点。结果如下:
在这里插入图片描述

可以看到最终剪枝为3个叶节点。每个叶节点显示患病情况、基尼值及数量占比。尽管rpart()函数能够清晰的输出决策过程,但使用rpart.plot函数绘制树状图,可以更直观地了解树模型的结构和分类规则,也有助于通俗解释树模型的结果,展示如下:
在这里插入图片描述

最后使用predict函数对新数据进行预测。新数据包括年龄(Age)为10岁、手术次数(Number)为1次、手术位置(Start)为3级的患者的基本信息。
在这里插入图片描述

函数返回值为该患者所属类别未患有/患有Kyphosis的预测概率,分别约为0.8161和0.1838,因而预测结果为未患有Kyphosis病变。

回归树实例

此决策树实例选择使用ISLR包中的Hitters数据集,它包括263个专业棒球运动员的各类信息,预测变量是home runs(平均本垒)和years played(职业经验),响应变量为运动员的Salary.首先构建大的初始回归树,为了让树足够大使用了较小的cp值,意味着只要回归模型总体R方增加就继续产生新的分支,后为避免过拟合问题,寻找最优cp值,cp的最佳值是致xerror最低的记录值,利用该值对决策树进行剪枝处理,最后利用剪枝后的决策树对新数据进行预测。
在这里插入图片描述

初始回归树的构建结果如上图所示,能够发现叶节点的数量较多,可能存在过拟合问题,利用决策树生成过程中交叉验证数据的观察结果的误差,找出最优对应的最优cp值,进行剪枝处理,结果如下。由于此部分侧决策树内容较多,便不妨决策树的输出结果,仅呈现图形。

在这里插入图片描述

最终剪枝结果如上图,每个终端节点显示运动员的薪资及原始数据中属于该节点的观察值的占比。
在这里插入图片描述

最后使用最终的剪枝树预测新的运动员薪资,基于职业经验和平均本垒(home runs).比如,某运动员有7年职业经验,平均本垒为4,则预测薪资约为502k.此部分R语言代码如下:

library(rpart)   
library(rpart.plot) #决策树更好看
#回归树构建【后剪枝】
library(ISLR)  
#初始回归树构建
tree <- rpart(Salary ~ Years + HmRun, data=Hitters, control=rpart.control(cp=.0001))
print(tree)
printcp(tree) 
rpart.plot(tree)
#剪枝
best<- tree$cptable[which.min(tree$cptable[,"xerror"]),"CP"]
print(best)
pruned_tree <- prune(tree, cp=best)
rpart.plot(pruned_tree)
# 预测
new <- data.frame(Years=7, HmRun=4)
predict(pruned_tree, newdata=new)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DeepSolution:比o1推理模型还强的RAG方案

一、为什么需要 DeepSolution&#xff1f; 1.1 复杂工程设计的挑战 在现代工程领域&#xff0c;设计一个满足多重复杂约束的解决方案是至关重要的。举个例子&#xff0c;假设我们需要设计一个在年降雨量 3000 毫米、膨胀土条件和频繁地震活动区域的安全高效医院建设方案。这种…

SpringBoot - 用责任链模式实现业务编排

文章目录 前因责任链&#xff1a;像工作台一样组织代码CodeSEQ3.1 定义处理器规范3.2 实现具体处理器3.3 共享上下文3.4 组装责任链 适用场景优势 前因 2000多行的业务逻辑里&#xff0c;各种校验规则、促销计算、库存操作像意大利面条一样缠绕在一起。最要命的是这样的代码结…

从家用显卡到AI文生视频——Wan2.1本地部署教程与一键包分享

今天要聊一聊AI文生视频的最新进展。一直以来&#xff0c;AI生成视频对硬件的要求都让人望而却步&#xff0c;尤其是家用显卡&#xff0c;总是感觉“心有余而力不足”。 AI文生视频以前 基本需要的显存大概几十上百G 但最近&#xff0c;阿里开源的 Wan2.1 彻底改变了这一局面…

Facebook营销自动化—— Python脚本 + 代理IP实现内容高效分发

目录 1. 引言&#xff1a;内容分发与Facebook营销的现状与痛点 2. 环境搭建与前期准备 2.1 开发环境与工具选择 2.2 获取代理IP 2.3 Facebook账号与开发者平台配置 3. Facebook内容分发的基本流程与策略 3.1 内容规划与策略制定 3.2 内容分发方式选择 3.3 风控与风险防…

TypeError: JSON.stringify cannot serialize cyclic structures

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

Manus邀请码申请与获取全攻略

大家好&#xff0c;我是吾鳴。 之前吾鳴给大家分享过一篇Manus的介绍文章——《全网疯抢邀请码的Manus到底是个啥&#xff1f;看完这篇你就懂了&#xff01;》&#xff0c;介绍了Manus是什么、与DeepSeek有些什么区别、生活中的应用场景以及工作中的应用场景。 今天吾鳴给大家分…

c++实现最大公因数和最小公倍数

最大公因数和最小公倍数的介绍 读这篇文章&#xff0c;请你先对最大公因数以及最小公倍数进行了解&#xff1a; 最大公因数&#xff08;英文名&#xff1a;gcd&#xff09; 定义&#xff1a;最大公因数&#xff0c;也称最大公约数&#xff0c;指两个或多个整数共有约数&…

Jetpack Compose — 入门实践

一、项目中使用 Jetpack Compose 从此节开始,为方便起见,如无特殊说明,Compose 均指代 Jetpack Compose。 开发工具: Android Studio 1.1 创建支持 Compose 新应用 新版 Android Studio 默认创建新项目即为 Compose 项目。 注意:在 Language 下拉菜单中,Kotlin 是唯一可…

PAM4信号技术

概述 PAM4(4-Level Pulse Amplitude Modulation)是一种四电平脉冲幅度调制技术,广泛应用于高速数据传输,特别是在100Gbps及以上的通信系统中。与传统的NRZ(Non-Return-to-Zero)相比,PAM4通过在每个符号周期内传输2个比特的信息,显著提升了数据传输效率。随着5G网络的发…

Visual Studio 2022新建c语言项目的详细步骤

步骤1&#xff1a;点击创建新项目 步骤2&#xff1a;到了项目模板 --> 选择“控制台应用” (在window终端运行代码。默认打印"Hello World") --> 点击 “下一步” 步骤3&#xff1a;到了配置新项目模块 --> 输入“项目名称” --> 更改“位置”路径&…

【UCB CS 61B SP24】 Lecture 25 26 - Minimum Spanning Trees 学习笔记

本文介绍了图论中的另一个经典问题&#xff1a;最小生成树&#xff08;MST&#xff09;&#xff0c;讲解并用 Java 实现了用于求解 MST 的两个经典算法 Prim 与 Kruskal。 1. 最小生成树介绍 最小生成树&#xff08;Minimum Spanning Tree&#xff0c;MST&#xff09;是图论中…

“此电脑”中删除WPS云盘方法(百度网盘通用)

&#x1f4e3;此方法适用于卸载WPS云盘后&#xff0c;WPS云盘图标依然在此电脑中显示的问题。 原理&#xff1a;通过注册来进行删除 步骤&#xff1a; WIN键R,打开运行窗口&#xff0c;输入regedit命令&#xff0c;来打开【注册表编辑器】&#xff1b; 从左侧&#xff0c;依…

鸿蒙跨平台框架ArkUI-X

01 引言 目前&#xff0c;移动端主流跨平台方案有Flutter、React Native、uni-app等等&#xff0c;还有刚推出不久的Compose-Multiplatform&#xff0c;真所谓是百花齐放。这些框架各有特点&#xff0c;技术实现各有差异&#xff0c;比如Flutter通过Dart编写的UI描述对接Flutte…

关于更新字段为空值——MybatisPlus框架

背景&#xff1a;我们在项目开发过程中&#xff0c;可能会经常遇到这样的问题&#xff0c;某个前端的字段&#xff0c;用户把原本有值的改为空值了&#xff0c;用户的意愿肯定是要去更新的&#xff0c;前端此时会把这个字段传"null"或空字符串&#xff0c;但我们后端…

CherryStudio调用DeepSeek API实现AI对话

目录 一、CherryStudio是什么&#xff1f;二、下载安装CherryStudio三、调用DeepSeek API&#xff08;以华为云为例&#xff09;1.新建服务模型2.获取API Key和API 地址3.添加模型检查连接 四、体验刚建立成功的deepseek五、总结 一、CherryStudio是什么&#xff1f; CherrySt…

夜莺监控 v8.0 新版通知规则 | 对接钉钉告警

对新版本通知规则还不太了解的用户可以阅读文章&#xff1a;《夜莺监控巨大革新&#xff1a;抽象出通知规则&#xff0c;增强告警通知的灵活性》。下面我们将以钉钉通知为例&#xff0c;介绍如何使用新版通知规则来对接钉钉通知。 上图是通知规则对接钉钉通知的示意逻辑图。 在…

pycharm找不到conda可执行文件

conda 24.9.2 在pycharm的右下角就可以切换python解释器了

第六课:数据库集成:MongoDB与Mongoose技术应用

本文详细介绍了如何在Node.js应用程序中集成MongoDB数据库&#xff0c;并使用Mongoose库进行数据操作。我们将涵盖MongoDB在Ubuntu 20系统中的安装、Bash命令的CRUD操作、Mongoose数据建模&#xff08;Schema/Model&#xff09;、关联查询与聚合管道&#xff0c;以及实战案例—…

小谈java内存马

基础知识 &#xff08;代码功底不好&#xff0c;就找ai优化了一下&#xff09; Java内存马是一种利用Java虚拟机&#xff08;JVM&#xff09;动态特性&#xff08;如类加载机制、反射技术等&#xff09;在内存中注入恶意代码的攻击手段。它不需要在磁盘上写入文件&#xff0c…

Swift系列01-Swift语言基本原理与设计哲学

本文将深入探讨Swift的核心原理、设计理念以及与Objective-C的对比 1. Swift与Objective-C的架构差异分析 Swift和Objective-C尽管可以无缝协作&#xff0c;但它们的架构设计存在本质差异。 1.1语言范式 Objective-C是一种动态语言&#xff0c;建立在C语言之上并添加了Smal…