R语言与机器学习中的回归方法学习笔记

2023-11-18

来源:http://blog.sina.com.cn/s/blog_62b37bfe0101hom5.html

key word:lars  rpart  randomForest  cp svm data(diabetes)prune()boosting mboost btree bagging ipred


        机器学习中的一些方法如决策树,随机森林,SVM,神经网络由于对数据没有分布的假定等普通线性回归模型的一些约束,预测效果也比较不错,交叉验证结果也能被接受。下面以R中lars包包含数据集diabetes为例说明机器学习中的回归方法。


一、数据集及交叉验证办法描述

        Diabetes数据集包含在R的lars包中,数据分为x,y,x2三个部分,因变量为y,数据是关于糖尿病的血液化验等指标。这个数据集最早被用在偏最小二乘回归的文章里。

       交叉验证采用指标NMSE来评价模型好坏。这一统计量是计算模型预测性能和基准模型的预测性能之间的比率。通常采用目标变量的平均值来作为基准模型。其取值范围通常为0~1。如果模型表现优于这个非常简单的基准模型预测,那么NMSE应明显小于1。NMSE的值越小,模型的性能就越好。NMSE的值大于1,意味着模型预测还不如简单地把所有个案的平均值作为预测值!

     交叉验证办法为将数据集分为5份,取4份作为训练集,1份作为测试集,共作5次,把误差平均起来作为衡量标准。选取代码如下:

 

  1. n<-length(dataset)  
  2. index1<-1:n  
  3. index2<-rep(1:5,ceiling(n/5))[1:n]  
  4. index2<-sample(index2,n)  


 

二、回归树

       决策树是通过一系列规则对数据进行分类的过程。它提供一种在什么条件下会得到什么值的类似规则的方法。决策树分为分类树和回归树两种,分类树对离散变量做决策树,回归树对连续变量做决策树。

    基本算法:

1.选择一个属性放置在根节点,为每个可能的属性值产生一个分支

2.将样本划分成多个子集,一个子集对应于一个分支

3.在每个分支上递归地重复这个过程,仅使用真正到达这个分支的样本

4.如果在一个节点上的所有样本拥有相同的类别,即停止该部分树的扩展

   

   构造决策树(集合划分)时选择属性:

1.ID3:Information Gain

2.C4.5:Gain Ratio

3.CART:Gini Index


在R中我们使用rpart包中的rpart()函数实现树回归。我们先把rpart包中的两个十分重要的函数介绍如下:

    构建回归树的函数:rpart()用法如下:

rpart(formula, data, weights,subset,na.action = na.rpart, method,

     model= FALSE, x = FALSE, y = TRUE, parms, control, cost, ...)

    主要参数说明:

fomula回归方程形式:例如 y~x1+x2+x3。

data数据:包含前面方程中变量的数据框(dataframe)。

na.action缺失数据的处理办法:默认办法是删除因变量缺失的观测而保留自变量缺失的观测。

method根据树末端的数据类型选择相应变量分割方法,本参数有四种取值:连续型“anova”;离散型“class”;计数型(泊松过程)“poisson”;生存分析型“exp”。程序会根据因变量的类型自动选择方法,但一般情况下最好还是指明本参数,以便让程序清楚做哪一种树模型。

parms用来设置三个参数:先验概率、损失矩阵、分类纯度的度量方法。

control控制每个节点上的最小样本量、交叉验证的次数、复杂性参量:即cp:complexitypamemeter,这个参数意味着对每一步拆分,模型的拟合优度必须提高的程度,等等。

        进行剪枝的函数:prune()用法如下:

prune(tree, cp, ...)

主要参数说明:

tree一个回归树对象,常是rpart()的结果对象。

cp复杂性参量,指定剪枝采用的阈值。cp全称为complexityparameter,指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度,用来节省剪枝浪费的不必要的时间,R内部是怎么计算的我不知道,希望读者能够补充。

 

运行代码:

 

  1. library(rpart.plot)  
  2. reg<-rpart(y~.,w)  
  3. rpart.plot(reg,type=2,faclen=T)  


 

      得到回归树:


 

        我们可以通过print(reg)来看到树的各个节点的细节。

        我们来进行交叉验证,运行代码如下:

 

  1. w<-diabetes[,2:3]  
  2. n<-length(w$y)  
  3. index1<-1:n  
  4. index2<-rep(1:5,ceiling(n/5))[1:n]  
  5. index2<-sample(index2,n)  
  6. NMSE<-rep(0,5)  
  7. NMSE0<-NMSE  
  8. for(i in 1:5){  
  9. m<-index1[index2==i]  
  10. reg<-rpart(y~.,w[-m,])  
  11. y0<-predict(reg,w[-m,])  
  12. y1<-predict(reg,w[m,])  
  13. NMSE0[i]<-mean((w$y[-m]-y0)^2)/mean((w$y[-m]-mean(w$y[-m]))^2)  
  14. NMSE[i]<-mean((w$y[m]-y1)^2)/mean((w$y[m]-mean(w$y[m]))^2)  
  15.  

       R中输出结果:

> NMSE

[1] 0.7892592 0.8857756 0.8619379 1.0072968 0.7238316

> NMSE0

[1] 0.3503767 0.3417909 0.3400387 0.3192845 0.3467186

        明显出现了过拟合现象,应该使用剪枝函数,对模型进行修正。

> reg$cptable

          CP            n      splitrelerror   xerror      xstd

0.29154165     0 1.0000000 1.0040015 0.05033316

0.08785891     1 0.7084583 0.8040962 0.04896667

0.05660089     2 0.6205994 0.7227529 0.04657623

0.02169615     3 0.5639986 0.6424826 0.04302580

0.02093950     4 0.5423024 0.6591446 0.04376777

0.01723601     50.52136290.6749867 0.04578783

0.01678503     6 0.5041269 0.6841483 0.04554068

0.01349365     8 0.4705568 0.6845580 0.04429950

0.01166564     9 0.4570632 0.7370893 0.04829371

100.01089168    11 0.43373190.7452419 0.05041336

110.01070564    12 0.42284020.7417955 0.05054043

120.01042308    14 0.40142890.7399988 0.05088835

130.01003363    15 0.39100580.7566972 0.05143535

140.01000000    17 0.37093860.7650728 0.05110011

      参照上述结果,选择合适的cp值。故修正为:

 

  1. reg2<-prune(reg,cp=0.025)  
  2. rpart.plot(reg2,type=2,faclen=T)  

      结果为:

 


 

        再次进行交叉验证(代码略)可以看到:

> NMSE

[1] 0.5982049 0.6995054 0.6826815 0.8970573 0.6407927

> NMSE0

[1] 0.5559462 0.5177565 0.4953384 0.5019682 0.5233709

        过拟合现象基本消除。

 

三、boosting回归

        Boosting方法是一种用来提高弱分类算法准确度的方法,这种方法通过构造一个预测函数系列,然后以一定的方式将他们组合成一个预测函数。他是一种框架算法,主要是通过对样本集的操作获得样本子集,然后用弱分类算法在样本子集上训练生成一系列的基分类器。他可以用来提高其他弱分类算法的识别率,也就是将其他的弱分类算法作为基分类算法放于Boosting框架中,通过Boosting框架对训练样本集的操作,得到不同的训练样本子集,用该样本子集去训练生成基分类器;每得到一个样本集就用该基分类算法在该样本集上产生一个基分类器,这样在给定训练轮数n 后,就可产生 n 个基分类器,然后Boosting框架算法将这 n个基分类器进行加权融合,产生一个最后的结果分类器,在这n个基分类器中,每个单个的分类器的识别率不一定很高,但他们联合后的结果有很高的识别率,这样便提高了该弱分类算法的识别率。

       Boosting方法简而言之就是采取少数服从多数的原理,他的合理性在于如果每个回归树的出错率为40%,那么1000棵决策树犯错误的概率就降到了4.40753e-11,这就比较小了。

      对diabetes数据做boosting回归,使用到的函数包为mboost,使用函数为mboost.用法如下:

mboost(formula, data = list(),
       baselearner = c("bbs", "bols", "btree", "bss", "bns"), ...)

其中formular需要使用到函数btree():

btree(..., tree_controls = ctree_control(stump = TRUE,
                                         mincriterion = 0,
                                         savesplitstats = FALSE))
       试运行下列代码:
  1. library(mboost)  
  2. reg<-mboost(y~btree(x2.ltg)+btree(x2.bmi)+btree(x2.bmi.ltg),  
  3. data=w,control=boost_control(nu=0.1))  

        我们可以得到boosting回归的信息,通过plot函数还有可视化结果。


 

        这里值得一提的是我在做boosting回归时为了减少工作量直接做了变量选择(这个选择与回归树的最终选择是一致的,所以也有一定的道理)。最后交叉验证的结果为:测试集NMSE为0.5513152,训练集NMSE为0.4656569。比起上次计算的回归树模型测试集NMSE为0.7036484,训练集NMSE为0.518876好了不少。

四、bagging回归

       与boosting回归想法类似,bagging回归的做法就是不断放回地对训练样本进行再抽样,对每个自助样本都建立一棵回归树,对于每一个观测,每棵树给一个预测,最后将其平均。

       对diabetes数据做bagging回归,使用到的函数包为ipred,使用函数为bagging(),用法如下:
bagging(formula, data, subset, na.action=na.rpart, ...)

主要参数介绍:

Formula:回归方程形式

Data:数据集

Control:对树枝的控制,使用函数rpart.control(),可以控制诸如cp值,xval等参量。

       输入代码:

  1. library(ipred)  
  2. reg<-bagging(y~.,data=w,coob=TRUE,control=rpart.control(cp=0.025))  

     结果为:



Baggingregression trees with 25 bootstrap replications 

Call:bagging.data.frame(formula = y ~ ., data = w, coob = TRUE, control =rpart.control(cp = 0.025))

Out-of-bagestimate of root mean squared error: 58.3648 

    使用交叉验证(代码略),得到结果:测试集NMSE为0.5705753,训练集NMSE为0.3906232。比起上次计算的回归树模型测试集NMSE为0.7036484,训练集NMSE为0.518876好了不少。

五、随机森林回归

     与bagging回归相比,随机森林则更进一步,不仅对样本进行抽样,还对变量进行抽样。

     对diabetes数据做随机森林回归,使用到的函数包为randomForest,使用函数为randomForest(),用法如下:
randomForest(formula, data=NULL, ..., subset, na.action=na.fail)

     这里值得一提的是,随机森林有个十分牛逼的性质,不会出现过拟合现象,这也省去了我们确定树的分类程度等一系列麻烦的事情。得到结果:测试集NMSE为0.08992529,训练集NMSE为0.08835731,效果显著提升。随机森林还可以输出自变量重要性度量,试运行代码:

  1. library(randomForest)  
  2. reg<-randomForest(y~.,data=w,importance=TRUE)  
  3. reg$importance  





    得到结果:

                %IncMSE IncNodePurity

x.glu        68.8034199     42207.351

x2.age       22.6784331     18569.370

x2.sex        6.2735713      2808.346

x2.bmi     1379.0675134    371372.494

x2.map      331.3925059    113411.547

x2.tc        18.6080948     14990.179

x2.ldl       24.3690847     17457.214

x2.hdl      216.2741620     64627.209

x2.tch      419.0451857     93688.855

x2.ltg     1514.0912885    379235.430

x2.glu       81.7568020     51984.121

x2.age.2      1.5242836     19364.582

x2.bmi.2     75.6345112     53635.024

x2.map.2      5.9156799     23049.475

x2.tc.2       1.6792683     15631.426

      (省略部分输出)

       其中第二列为均方误差递减意义下的重要性,第三列为精确度递减意义下的重要性。

六、其他的回归方法

      除去我们所说的以上4种方法外,还有人工神经网络回归,SVM回归,他们可以通过nnet,rminer包中有关函数实现,这里我们从略。

 

       在结束本文之前,我想我们可以做一件更有意义的事。在介绍diabetes数据集时,我们提到了这个数据最早是一个关于偏最小二乘的例子。那么想必他与这个模型的契合度还是不错的,我们可以尝试去算算利用偏最小二乘得到的训练集与测试集的NMSE。

代码如下:

  1. library(lars)  
  2. library(pls)  
  3. NMSE<-rep(0,5)  
  4. NMSE0<-NMSE  
  5. for(i in 1:5){  
  6. m<-index1[index2==i]  
  7. reg.pls <- plsr(y x2, 64, data diabetes[-m,], validation ="CV")  
  8. y0<-predict(reg.pls,diabetes[-m,])  
  9. y1<-predict(reg.pls,diabetes[m,])  
  10. NMSE0[i]<-mean((diabetes$y[-m]-y0)^2)/mean((diabetes$y[-m]-mean(diabetes$y[-m]))^2)  
  11. NMSE[i]<-mean((diabetes$y[m]-y1)^2)/mean((diabetes$y[m]-mean(diabetes$y[m]))^2)  
  12.  







      运行结果:测试集NMSE为0.6094071,训练集NMSE为0.4031211。这里也仅仅是得到了一个优于回归树,与bagging回归相当,不如随机森林的一个结果。也说明了机器学习方法在实际问题中还是有一定优势的。但这绝不意味着这样的回归可以代替OLS,毕竟这些数据挖掘的方法在表达式的简洁程度,计算量等诸多方面还是存在着或多或少的不足。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R语言与机器学习中的回归方法学习笔记 的相关文章

随机推荐

  • 当服务器无法访问,如何快速定位问题点

    工作和生活中 我们难免会遇到这样的问题 这种情况出现时 如何快速定位排查呢 一 了解什么是域名 VS IP 1 什么是域名 www baidu com 2 为什么用域名通信 不直接用IP通信 ip地址不好记忆 如 124 56 78 333
  • XSS大全

    XSS的原理和特性 xss 将用户的输入当作前端代码执行 注入攻击的本质 是把用户输入的数据当做代码执行 这里有两个关键条件 第一个是用户能够控制输入 第二个是原本程序要执行的代码 拼接了用户输入的数据 html 定义了网页的结构 css
  • MSB和LSB,建议先看下面(其实就是大小端的问题)

    最高有效位 MSB 指二进制中最高值的比特 在16比特的数字音频中 其第1个比特便对16bit的字的数值有最大的影响 例如 在十进制的15389这一数字中 相当于万数那1行 1 的数字便对数值的影响最大 比较与之相反的 最低有效位 LSB
  • Docker使C盘爆满问题

    问题描述 C爆满 查看大文件发现Docker文件超大 猜想应该是Docker镜像文件或者其他文件存于C盘导致 解决 安装docker后会自动创建两个发行版 wsl l v all 关闭Docker 关闭所有发行版 wsl shutdown
  • 将unique_ptr转换为shared_ptr

    std unique ptr
  • CTF入门学习笔记——Crypto密码(古典密码)

    文章目录 CTF入门学习笔记 Crypto密码 古典密码 凯撒密码 看我回旋踢 摩斯密码 摩斯 维吉尼亚密码 Vigen re 栅栏密码 篱笆墙的影子 栅栏密码 篱笆墙的影子 猪圈密码 待补充 CTF入门学习笔记 Crypto密码 古典密码
  • 苹果sf字体_全网首发丨iOS13越狱系统字体分析+iOS13新字体分享

    根据可靠消息分析 最快明天 最迟后天 iOS13系统的越狱就要来了 雨哥也 提前解包了iOS13 2系统的原生字体出来研究一下 未雨绸缪 有备无患 看看iOS12升级到iOS13后系统字体做了哪些升级和变化 喜欢手机字体美化的要认真往下看
  • Coverage官方手册翻译

    下面是官方手册的翻译 Coverage手册 Coverage命令行使用 当你安装 coverage py 将一个名为coverage的命令行脚本py放在Python脚本目录中 为了帮助多版本安装 它还将创建coverage2或coverag
  • 剑指 Offer 62. 圆圈中最后剩下的数字(简单 约瑟夫问题 递归 数学)

    剑指 Offer 62 圆圈中最后剩下的数字 0 1 n 1这n个数字排成一个圆圈 从数字0开始 每次从这个圆圈里删除第m个数字 删除后从下一个数字开始计数 求出这个圆圈里剩下的最后一个数字 例如 0 1 2 3 4这5个数字组成一个圆圈
  • 打印 pyspark.sql.dataframe.DataFrame 有哪些列

    在 PySpark 中 要打印 pyspark sql dataframe DataFrame 的列 可以使用 columns 属性 以下是一个示例代码 from pyspark sql import SparkSession 创建 Spa
  • 串口发送QString buff=“81 20 33 0A 0d“,如何接收 “Q 3” 并换行回车,

    采用Qt写 需要一个showHex函数 将接收的一串QByteArray类型的16进制 转化为对应的字符串16进制 QString ShowHex QByteArray str QDataStream out str QIODevice R
  • vue基础知识八:为什么data属性是一个函数而不是一个对象?

    一 实例和组件定义data的区别 vue实例的时候定义data属性既可以是一个对象 也可以是一个函数 const app new Vue el app 对象格式 data foo foo 函数格式 data return foo foo 组
  • JVM内存模型图解(包含堆栈方法区例子和图解)

    下图是完整的虚拟机模型 我们主要是了解三个 1 堆区 heap 存储的全部是对象 每个对象都包含一个与之对应的class的信息 jvm只有一个堆区 heap 被所有线程共享 堆中不存放基本类型和对象引用 只存放对象本身 2 栈区 stack
  • 【Java数据类型】各种数据类型的相互转换总结

    基础数据类型包括 byte short int long float double char String boolean 在许多场合需要用到它们的相互转换 本文 将介绍几种转换方式 以及对转换方式的原理简要介绍 文章目录 法则与特性 字节
  • 三星一体计算机参数,三星四核机皇 Galaxy Note 10.1初体验

    若将时间往前推移10年那时的手机还谈不上智能 如果是五年前就正是笔记本电脑市场燃起星星之火的时候 而两年前平板电脑的概念才开始深入人心 当这些产品一个个走上历史舞台的时候可能很单纯也很迷茫 想法很好却受制于科技发展的前进步伐有些缓慢 如今
  • 6.1 PyTorch简单二分类模型

    欢迎订阅本专栏 PyTorch深度学习实践 订阅地址 https blog csdn net sinat 33761963 category 9720080 html 第二章 认识Tensor的类型 创建 存储 api等 打好Tensor的
  • 从源码的角度回答“mybatis的#{} 和${}有什么区别”?

    java程序员面试的时候 碰上面试官问 mybatis 的 和 有什么区别 大概率你会这样回答 1 是预编译处理 是字符串替换 2 MyBatis在处理 时 会将sql中的 替换为 号 调用PreparedStatement的set方法来赋
  • 2min搞定 mac pycharm新建&导入python项目

    mac pycharm新建和导入python项目 虚拟环境配置 下载类库 一 通用设置 step1 通过自定义配置 指定默认虚拟环境变量 step2 设置虚拟环境和指定默认工作空间 step3 导入或者新建python项目 二 pychar
  • 杰里之蓝牙耳机距离及 天线匹配 调试方法篇

    一 t PCB layout 注意事项 1 1 保证 信号完整性 芯片 VMCU VDDIO BTAVDD RTCVDD 退偶电容地线回路要尽量短 SW BTAVDD 回路尽量短 地线完整 电 源线要尽量粗 一般 0 3MM 以上 请参考例
  • R语言与机器学习中的回归方法学习笔记

    来源 http blog sina com cn s blog 62b37bfe0101hom5 html key word lars rpart randomForest cp svm data diabetes prune boosti