京公网安备 11010802034615号
经营许可证编号:京B2-20210330
机器学习中的一些方法如决策树,随机森林,SVM,神经网络由于对数据没有分布的假定等普通线性回归模型的一些约束,预测效果也比较不错,交叉验证结果也能被接受。下面以R中lars包包含数据集diabetes为例说明机器学习中的回归方法。
一、数据集及交叉验证办法描述
Diabetes数据集包含在R的lars包中,数据分为x,y,x2三个部分,因变量为y,数据是关于糖尿病的血液化验等指标。这个数据集最早被用在偏最小二乘回归的文章里。
交叉验证采用指标NMSE来评价模型好坏。这一统计量是计算模型预测性能和基准模型的预测性能之间的比率。通常采用目标变量的平均值来作为基准模型。其取值范围通常为0~1。如果模型表现优于这个非常简单的基准模型预测,那么NMSE应明显小于1。NMSE的值越小,模型的性能就越好。NMSE的值大于1,意味着模型预测还不如简单地把所有个案的平均值作为预测值!
交叉验证办法为将数据集分为5份,取4份作为训练集,1份作为测试集,共作5次,把误差平均起来作为衡量标准。选取代码如下:
二、回归树
决策树是通过一系列规则对数据进行分类的过程。它提供一种在什么条件下会得到什么值的类似规则的方法。决策树分为分类树和回归树两种,分类树对离散变量做决策树,回归树对连续变量做决策树。
基本算法:
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全称为complexity parameter,指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度,用来节省剪枝浪费的不必要的时间,R内部是怎么计算的我不知道,希望读者能够补充。
进一步补充一点关于CP值的东西:建立树模型要权衡两方面问题,一个是要拟合得使分组后的变异较小,另一个是要防止过度拟合,而使模型的误差过大,前者的参数是CP,后者的参数是Xerror。所以要在Xerror最小的情况下,也使CP尽量小。如果认为树模型过于复杂,我们需要对其进行修剪 。(摘自推酷上的《分类-回归树模型(CART)在R语言中的实现》)
运行代码:
得到回归树:
我们可以通过print(reg)来看到树的各个节点的细节。
我们来进行交叉验证,运行代码如下:
w<-diabetes[,2:3]
n<-length(w$y)
index1<-1:n
index2<-rep(1:5,ceiling(n/5))[1:n]
index2<-sample(index2,n)
NMSE<-rep(0,5)
NMSE0<-NMSE
for(i in 1:5){
m<-index1[index2==i]
reg<-rpart(y~.,w[-m,])
y0<-predict(reg,w[-m,])
y1<-predict(reg,w[m,])
NMSE0[i]<-mean((w$y[-m]-y0)^2)/mean((w$y[-m]-mean(w$y[-m]))^2)
NMSE[i]<-mean((w$y[m]-y1)^2)/mean((w$y[m]-mean(w$y[m]))^2)
}
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 split relerror xerror xstd
1 0.29154165 0 1.0000000 1.0040015 0.05033316
2 0.08785891 1 0.7084583 0.8040962 0.04896667
3 0.05660089 2 0.6205994 0.7227529 0.04657623
4 0.02169615 3 0.5639986 0.6424826 0.04302580
5 0.02093950 4 0.5423024 0.6591446 0.04376777
6 0.01723601 50.5213629 0.6749867 0.04578783
7 0.01678503 6 0.5041269 0.6841483 0.04554068
8 0.01349365 8 0.4705568 0.6845580 0.04429950
9 0.01166564 9 0.4570632 0.7370893 0.04829371
10 0.01089168 11 0.43373190.7452419 0.05041336
11 0.01070564 12 0.42284020.7417955 0.05054043
12 0.01042308 14 0.40142890.7399988 0.05088835
13 0.01003363 15 0.39100580.7566972 0.05143535
14 0.01000000 17 0.37093860.7650728 0.05110011
参照上述结果,选择合适的cp值。故修正为:
reg2<-prune(reg,cp=0.025)结果为:
再次进行交叉验证(代码略)可以看到:
> 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)) 试运行下列代码:
我们可以得到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等参量。
输入代码:
library(ipred)结果为:
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,效果显著提升。随机森林还可以输出自变量重要性度量,试运行代码:
library(randomForest)得到结果:
%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。
代码如下:
library(lars)
library(pls)
NMSE<-rep(0,5)
NMSE0<-NMSE
for(i in 1:5){
m<-index1[index2==i]
reg.pls <- plsr(y ~ x2, 64, data = diabetes[-m,], validation ="CV")
y0<-predict(reg.pls,diabetes[-m,])
y1<-predict(reg.pls,diabetes[m,])
NMSE0[i]<-mean((diabetes$y[-m]-y0)^2)/mean((diabetes$y[-m]-mean(diabetes$y[-m]))^2)
NMSE[i]<-mean((diabetes$y[m]-y1)^2)/mean((diabetes$y[m]-mean(diabetes$y[m]))^2)
}
运行结果:测试集NMSE为0.6094071,训练集NMSE为0.4031211。这里也仅仅是得到了一个优于回归树,与bagging回归相当,不如随机森林的一个结果。也说明了机器学习方法在实际问题中还是有一定优势的。但这绝不意味着这样的回归可以代替OLS,毕竟这些数据挖掘的方法在表达式的简洁程度,计算量等诸多方面还是存在着或多或少的不足。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在数据分析、质量控制、科研实验等场景中,数据波动性(离散程度)的精准衡量是判断数据可靠性、稳定性的核心环节。标准差(Stan ...
2026-01-29在数据分析、质量检测、科研实验等领域,判断数据间是否存在本质差异是核心需求,而t检验、F检验是实现这一目标的经典统计方法。 ...
2026-01-29统计制图(数据可视化)是数据分析的核心呈现载体,它将抽象的数据转化为直观的图表、图形,让数据规律、业务差异与潜在问题一目 ...
2026-01-29箱线图(Box Plot)作为数据分布可视化的核心工具,能清晰呈现数据的中位数、四分位数、异常值等关键统计特征,广泛应用于数据分 ...
2026-01-28在回归分析、机器学习建模等数据分析场景中,多重共线性是高频数据问题——当多个自变量间存在较强的线性关联时,会导致模型系数 ...
2026-01-28数据分析的价值落地,离不开科学方法的支撑。六种核心分析方法——描述性分析、诊断性分析、预测性分析、规范性分析、对比分析、 ...
2026-01-28在机器学习与数据分析领域,特征是连接数据与模型的核心载体,而特征重要性分析则是挖掘数据价值、优化模型性能、赋能业务决策的 ...
2026-01-27关联分析是数据挖掘领域中挖掘数据间潜在关联关系的经典方法,广泛应用于零售购物篮分析、电商推荐、用户行为路径挖掘等场景。而 ...
2026-01-27数据分析的基础范式,是支撑数据工作从“零散操作”走向“标准化落地”的核心方法论框架,它定义了数据分析的核心逻辑、流程与目 ...
2026-01-27在数据分析、后端开发、业务运维等工作中,SQL语句是操作数据库的核心工具。面对复杂的表结构、多表关联逻辑及灵活的查询需求, ...
2026-01-26支持向量机(SVM)作为机器学习中经典的分类算法,凭借其在小样本、高维数据场景下的优异泛化能力,被广泛应用于图像识别、文本 ...
2026-01-26在数字化浪潮下,数据分析已成为企业决策的核心支撑,而CDA数据分析师作为标准化、专业化的数据人才代表,正逐步成为连接数据资 ...
2026-01-26数据分析的核心价值在于用数据驱动决策,而指标作为数据的“载体”,其选取的合理性直接决定分析结果的有效性。选对指标能精准定 ...
2026-01-23在MySQL查询编写中,我们习惯按“SELECT → FROM → WHERE → ORDER BY”的语法顺序组织语句,直觉上认为代码顺序即执行顺序。但 ...
2026-01-23数字化转型已从企业“可选项”升级为“必答题”,其核心本质是通过数据驱动业务重构、流程优化与模式创新,实现从传统运营向智能 ...
2026-01-23CDA持证人已遍布在世界范围各行各业,包括世界500强企业、顶尖科技独角兽、大型金融机构、国企事业单位、国家行政机关等等,“CDA数据分析师”人才队伍遵守着CDA职业道德准则,发挥着专业技能,已成为支撑科技发展的核心力量。 ...
2026-01-22在数字化时代,企业积累的海量数据如同散落的珍珠,而数据模型就是串联这些珍珠的线——它并非简单的数据集合,而是对现实业务场 ...
2026-01-22在数字化运营场景中,用户每一次点击、浏览、交互都构成了行为轨迹,这些轨迹交织成海量的用户行为路径。但并非所有路径都具备业 ...
2026-01-22在数字化时代,企业数据资产的价值持续攀升,数据安全已从“合规底线”升级为“生存红线”。企业数据安全管理方法论以“战略引领 ...
2026-01-22在SQL数据分析与业务查询中,日期数据是高频处理对象——订单创建时间、用户注册日期、数据统计周期等场景,都需对日期进行格式 ...
2026-01-21