注意 本来是用r markdown写的所有代码放到Rstudio里面都可以运行,无奈csdn不支持这种东西
理论
所谓理论不过简单理解,并没有什么强力的证明
验证集方法
验证集方法,在Andrew的课里面涉及到过,就是将样本一部分作为训练集,一部分作为测试集,这种方法有两个缺点
- 受训练集的影响波动性很大
- 由于被训练的观测很少,统计方法表现不好
留-交叉验证(LOOCV)
这种方法用伪代码描述就是
for i = 1:n
将第i项作为测试集
将剩余的作为训练集训练,计算均方误差
这种方法训练的均方误差就是
CV(n)=1nΣni=1MSEi
这种方法的计算时间比较长,不过《ISLR》中说在用最小二乘法时可以用如下公式将时间缩短(函数cv.glm)并没有用这种方法
CVn=1nΣni=1(yi−yi^1−hi)2
其中 hi 是杠杆值
K折交叉法
这种方法只是LOOCV的简单扩展,就是吧数据分为k组,然后每次选一组作为测试集,其余作为验证集即可,一般令k=5或10不会产生较大的方差偏差权衡问题,感觉这种和min-batch有异曲同工之妙.
自助法bootstrap
自助法就是有放回的重数据集中抽取数据组成样本,然后在样本上训练,取均值作为输出的统计量,一般来说设概率是均匀的。
验证集方法
训练集
library(ISLR)
set.seed(1)
train = sample(392,196)
拟合线性模型
lm.fit = lm(mpg~horsepower,data=Auto,subset = train)
残差计算
attach(Auto)
rss = mean((mpg[-train]-predict(lm.fit,Auto[-train,]))^2)
高次多项式拟合
rss = rep(0,time=10)
for(i in 1:10){
lm.tmp<-lm(mpg~poly(horsepower,i),data = Auto,subset = train)
rss[i] <- mean((mpg[-train]-predict(lm.tmp,Auto[-train,]))^2)
}
plot(rss)
留-交叉验证法(LOOCV)
library(boot)
cv.err = rep(0,5)
for( i in 1:5){
glm.fit = glm(mpg~poly(horsepower,i),data = Auto)
cv.err[i] = cv.glm(Auto,glm.fit)$delta[1]
}
plot(cv.err)
运行发现这种方法非常慢
k折交叉验证法
可以同样的使用cv.glm() 来做k折交叉验证,只需将k设定一个值,返回值delta[1]是标准估计,而第二个数值是偏差矫正后的结果
cv.err <- rep(0,10)
for(i in 1:10){
glm.fit <- glm(mpg~poly(horsepower,i),data = Auto)
cv.err[i] = cv.glm(Auto,glm.fit,K=10)$delta[1]
}
plot(cv.err)
自助法
r 中的包boot中的方法boot可以用来执行自助法,使用boot需要提供一个计算统计量的函数,第一个参数默认为数据,第二个参数接受index
alpha.fn <- function(data,index){
X= data$X[index]
Y=data$Y[index]
return((var(Y)-cov(X,Y))/(var(X)+var(Y)-2*cov(X,Y)))
}
#自助法模拟
boot(Portfolio,alpha.fn,R=1000)#数据,统计量函数,次数
将boot作为变量返回,我们会发现很多东西,
boo = boot(Portfolio,alpha.fn,R=1000)
boo$t0 #统计量结果
boo$t #每次计算值
boo$weights #每一项所占权值
自助法估计线性回归模型精度
boot.fn <- function(data,index){
return(coef(lm(mpg~horsepower,data=data,subset = index)))
}
boot.fn(Auto,1:392)
boot(Auto,boot.fn,1000)
#与summary的结果比较
summary(lm(mpg~horsepower,data = Auto))$coef