
机器学习中的一些方法如决策树,随机森林,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全称为complexity parameter,指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度,用来节省剪枝浪费的不必要的时间,R内部是怎么计算的我不知道,希望读者能够补充。
进一步补充一点关于CP值的东西:建立树模型要权衡两方面问题,一个是要拟合得使分组后的变异较小,另一个是要防止过度拟合,而使模型的误差过大,前者的参数是CP,后者的参数是Xerror。所以要在Xerror最小的情况下,也使CP尽量小。如果认为树模型过于复杂,我们需要对其进行修剪。
运行代码:
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.72592 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.087851 1 0.708458
3 0.8040962 0.046667
3 0.056600 2 0.620599
4 0.7227529 0.04657623
4 0.0216961
5 3 0.563998
6 0.24826 0.04302580
5 0.02093950 4 0.5423024 0.659144
6 0.04376777
6 0.01723601 50.5213629 0.674986
7 0.04578783
7 0.01678503 6 0.5041269 0.6841483 0.045540688 0.01349365 8 0.4705568 0.6845580 0.04429950
9 0.011665 9 0.4570632 0.73703 0.04829371
10 0.010168 11 0.43373190.7452419 0.05041336
11 0.010705 12 0.42284020.7417955 0.05054043
12 0.01042308 14 0.401420.7399988 0.05088835
13 0.01003363 15 0.39100580.7566972 0.05143535
14 0.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.70573 0.07927 > NMSE0
[1] 0.5559462 0.5177565 0.4953384 0.5019682 0.5233709 过拟合现象基本消除。
(未完待续。。)
