Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >R语言模拟:Cross Validation

R语言模拟:Cross Validation

作者头像
量化小白
发布于 2019-08-29 08:41:17
发布于 2019-08-29 08:41:17
3.2K00
代码可运行
举报
运行总次数:0
代码可运行

前两篇在理论推导和模拟的基础上,对于误差分析中的偏差方差进行了分析。本文在前文的基础上,分析一种常用的估计预测误差进而可以参数优化的方法:交叉验证,并通过R语言进行模拟。

K-FOLD CV

交叉验证是数据建模中一种常用方法,通过交叉验证估计预测误差并有效避免过拟合现象。简要说明CV(CROSS VALIDATION)的逻辑,最常用的是K-FOLD CV,以K = 5为例。

将整个样本集分为K份,每次取其中一份作为Validation Set,剩余四份为Trainset,用Trainset训练模型,然后计算模型在Validation set上的误差,循环k次得到k个误差后求平均,作为预测误差的估计量。

除此之外,比较常用的还有LOOCV,每次只留出一项做Validation,剩余项做Trainset。

参数优化

对于含有参数的模型,可以分析模型在不同参数值下的CV的误差,选取误差最小的参数值。

误区

ESL 7.10.2中提到应用CV的两种方法,比如对于一个包含多个自变量的分类模型,建模中包括两方面,一个是筛选出预测能力强的变量,一个是估计最佳的参数。因此有两种使用CV的方法(以下内容摘自ESL 7.10.2)

1

1.Screen the predictors: find a subset of “good” predictors that show fairly strong (univariate) correlation with the class labels

2.Using just this subset of predictors, build a multivariate classifier.

3.Use cross-validation to estimate the unknown tuning parameters and to estimate the prediction error of the final model.

2

1. Divide the samples into K CV folds(group) at random.

2. For each fold k = 1,2,...,K

(a) Find a subset of "good" predictors that show fairly strong correlation with the class labels, using all of the samples except those in fold k.

(b) Using just this subset of predictors,build a multivariate classifier,using all of the samples except those in fold K.

(c) Use the classifier to predict rhe class labels for the samples in fold k.

简单来说,第一种方法是先使用全样本筛出预测能力强的变量,仅使用这部分变量进行建模,然后用这部分变量建立的模型通过CV优化参数;第二种方法是对全样本CV后,在CV过程中进行筛选变量,然后用筛选出来的变量优化参数,这样CV中每个循环里得到的预测能力强的变量有可能是不一样的。

我们经常使用的是第一种方法,但事实上第一种方法是错误的,直接通过全样本得到的预测能力强的变量,再进行CV,计算出来的误差一定是偏低的。因为筛选过程使用了全样本,再使用CV,用其中K-1份预测1份,使用的预测能力强的变量中实际上包含了这一份的信息,因此存在前视误差。

(The problem is that the predictors have an unfair advantage, as they were chosen in step (1) on the basis of all of the samples. Leaving samples out after the variables have been selected does not correctly mimic the application of the classifier to a completely independent test set, since these predictors “have already seen” the left out samples.)

作者给出一个可以验证的例子:

考虑包含50个样本的二分类集合,两种类别的样本数相同,5000个服从标准正态分布的自变量且均与类别标签独立。这种情况下,理论上使用任何模型得到的误差都应该是50%

如果此时我们使用上述方法1找出100个与类别标签相关性最强的变量,然后仅对这100个变量使用KNN算法,并令K=1,CV得到的误差仅有3%,远远低于真实误差50%。

作者使用了5-FOLD CV并且计算了CV中每次Validation set 中10个样本的自变量与类别的相关系数,发现此时相关系数平均值为0.28,远大于0。

而使用第二种方法计算的相关系数远低于第一种方法。

模拟

我们通过R语言模拟给出一个通过CV估计最优参数的例子,例子为上一篇右下图的延伸。

样本: 80个样本,20个自变量,自变量均服从[0,1]均匀分布,因变量定义为:

Y = ifelse(X1+X2+...+X10>5,1,0)

使用Best Subset Regression建模(就是在线性回归的基础上加一步筛选最优自变量组合),模型唯一待定参数为Subset Size p,即最优的自变量个数。

通过10-Fold CV计算不同参数p下的预测误差并给出最优的p值,Best Subset Regression可以通过函数regsubsets实现,最终结果如下:

对比教材中的结果

其中,红色线为真实的预测误差,蓝色线为10-FOLD CV计算出的误差,bar为1标准误。可以得出以下结论:

  1. CV估计的误差与实际预测误差的数值大小、趋势变化基本相同,并且真实预测误差基本都在CV1标准误以内。
  2. p = 10附近误差最小,表明参数p应设定为10,这也与样本因变量定义相符。

可以直接运行的R代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setwd('xxxx')
library(leaps) 
library(DAAG)
library(caret)
lm.BestSubSet<- function(trainset,k){
  lm.sub <- regsubsets(V21~.,trainset,nbest =1,nvmax = 20)
  summary(lm.sub)
  coef_lm <- coef(lm.sub,k)
  strings_coef_lm <- coef_lm
  x <- paste(names(coef_lm)[2:length(coef_lm)], collapse ='+')
  formulas <- as.formula(paste('V21~',x,collapse=''))
  return(formulas)
}

# ====================   get error ===============================
getError <- function(k,num,modeltype,seeds,n_test){
  set.seed(seeds)
  testset <- as.data.frame(matrix(runif(n_test*21,0,1),n_test))
  
  Allfx_hat <- matrix(0,n_test,num)
  Ally <- matrix(0,n_test,num)
  Allfx <- matrix(0,n_test,num)
   
  # 模拟 num次   
  for (i in 1:num){
    trainset <- as.data.frame(matrix(runif(80*21,0,1),80))
    fx_train <- ifelse(trainset[,1] +trainset[,2] +trainset[,3] +trainset[,4] +trainset[,5]+
                         trainset[,6] +trainset[,7] +trainset[,8] +trainset[,9] +trainset[,10]>5,1,0)   
    trainset[,21] <- fx_train   
    fx_test <- ifelse(testset[,1] +testset[,2] +testset[,3] +testset[,4] +testset[,5]+
                        testset[,6] +testset[,7] +testset[,8] +testset[,9] +testset[,10]>5,1,0)
    
    testset[,21] <- fx_test 
    
    
    # best subset
    lm.sub <- lm(formula = lm.BestSubSet(trainset,k),trainset)
    probs <- predict(lm.sub,testset[,1:20], type = 'response')
    
    
    Allfx_hat[,i] <- probs
    Ally[,i] <- testset[,21]
    Allfx[,i] <- fx_test
    
  } 
  # 计算方差、偏差等
  
  # irreducible <- sigma^2
  
  irreducible  <- mean(apply( Allfx - Ally  ,1,var))
  SquareBais  <- mean(apply((Allfx_hat - Allfx)^2,1,mean))
  Variance <- mean(apply(Allfx_hat,1,var))
  
  # 回归或分类两种情况
  if (modeltype == 'reg'){
    PredictError <- irreducible + SquareBais + Variance 
  }else{
    PredictError <- mean(ifelse(Allfx_hat>=0.5,1,0)!=Allfx)
  }
  result <- data.frame(k,irreducible,SquareBais,Variance,PredictError)
  return(result)
}


# -------------------- classification -------------------
modeltype <- 'classification'
num <- 100
n_test <- 1000
seeds <- 4

all_p <- seq(2,20,1)
result <- getError(1,num,modeltype,seeds,n_test)
for (i in all_p){
  result <- rbind(result,getError(i,num,modeltype,seeds,n_test)) 
}

# ==================== CV  =========================

fun_cv <- function(trainset,kfold=10,seed_num =3,p){
  set.seed(seed_num)
  folds<-createFolds(y=trainset$V21,kfold) 
  misrate <- NULL
  
  for (i in(1:kfold)){
    
    train_cv<-trainset[-folds[[i]],]
    test_cv<-trainset[folds[[i]],]
    
    model <- lm(formula = lm.BestSubSet(train_cv,p),train_cv)
    result  <- predict(model,type='response',test_cv)
    
    # result 
    misrate[i] <- mean( ifelse(result>=0.5,1,0) != test_cv$V21)
  }
  sderror <- sd(misrate)/(length(misrate)^0.5)
  misrate <- mean(misrate)
  result <- data.frame(p,misrate,sderror)
  return(result) 
}

plot_error <- function(x, y, sd, len = 1, col = "black") {
  len <- len * 0.05
  arrows(x0 = x, y0 = y, x1 = x, y1 = y - sd, col = col, angle = 90, length = len)
  arrows(x0 = x, y0 = y, x1 = x, y1 = y + sd, col = col, angle = 90, length = len)
}


# ================================   draw ==============================
# seed =   9,10,   92,65114,  10912
seed_num =  9
trainset <- as.data.frame(matrix(runif(80*21,0,1),80))
trainset[,21] <- ifelse(trainset[,1] +trainset[,2] +trainset[,3] +trainset[,4] +trainset[,5]+
                          trainset[,6] +trainset[,7] +trainset[,8] +trainset[,9] +trainset[,10]>5,1,0)

resultcv <- fun_cv(trainset,kfold = 10,seed_num,p = 1)
for (p in 2:20){
  resultcv <- rbind(resultcv,fun_cv(trainset,kfold = 10,seed_num,p))
}

png(file = "Cross Validation_large_testset.png")

plot(result$k,result$PredictError,type = 'o',col = 'red',
     xlim = c(0,20),ylim = c(0,0.6),xlab = '', ylab ='', lwd = 2)
par(new = T)

plot(resultcv$p,resultcv$misrate,type='o',lwd=2,col='blue',ylim = c(0,0.6),xlim = c(0,20),
     xlab = 'Subset Size p', ylab = 'Misclassification Error')
plot_error(resultcv$p,resultcv$misrate,resultcv$sderror,col = 'blue',len = 1)
dev.off()

参考文献

Ruppert D. The Elements of Statistical Learning: Data Mining, Inference, and Prediction[J]. Journal of the Royal Statistical Society, 2010, 99(466):567-567.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量化小白躺平记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
R语言模拟:Bias Variance Decomposition
接上一篇《R语言模拟:Bias-Variance trade-off》,本文通过模拟分析算法的泛化误差、偏差、方差和噪声之间的关系,是《element statistical learning》第七章的一个案例。
量化小白
2019/08/29
1.2K0
R语言模拟:Bias Variance Decomposition
生信代码:机器学习-训练模型
在构建预测模型的开始可以使用数据分割构建训练集和测试集,也可以在训练集中用于执行交叉验证或自举(bootstrapping),以评估模型。
科研菌
2021/02/19
1.5K1
生信代码:机器学习-训练模型
使用scikit-learn进行建模预测和评估操作_泰坦尼克号获救预测
# coding: utf-8 # In[142]: import pandas as pd import numpy as np import matplotlib.pyplot as plt # In[143]: # 导入数据 titanic = pd.read_csv('train.csv') titanic.head(5) # print(titanic.describe()) # In[144]: titanic['Age'] = titanic['Age'].fillna(tit
统计学家
2019/04/10
4790
R语言模拟:Bias Variance Trade-Off
本文是对ESL中第七章一个小案例的复现,主要是对机器学习算法误差的分解,全文包括理论推导和模拟两部分。
量化小白
2019/08/29
7870
R语言模拟:Bias Variance Trade-Off
用R语言实现神经网络预测股票实例
因此,我们使用神经网络来解决分类问题。通过分类,我们指的是按类别对数据进行分类的分类。例如,水果可分为苹果,香蕉,橙等。
拓端
2020/07/17
1.7K0
用R语言实现神经网络预测股票实例
手把手教你R语言随机森林使用
随机森林是常用的非线性用于构建分类器的算法,它是由数目众多的弱决策树构建成森林进而对结果进行投票判断标签的方法。
生信学习者
2024/06/11
7020
手把手教你R语言随机森林使用
Scikit-learn 秘籍 第五章 模型后处理
这个秘籍中,我们会创建交叉验证,它可能是最重要的模型后处理验证练习。我们会在这个秘籍中讨论 k-fold 交叉验证。有几种交叉验证的种类,每个都有不同的随机化模式。K-fold 可能是一种最熟知的随机化模式。
ApacheCN_飞龙
2022/12/01
5610
Scikit-learn 秘籍 第五章 模型后处理
第8章 集成学习 笔记
将多个分类器的预测结果进行组合得到最终决策,来获得更好的分类及回归性能。单一分类器只适合于某种特定类型的数据,很难保证得到最佳分类模型,如果对不同算法的预测结果取平均,相比一个分类器,可能会获得更好的分类模型。bagging, boosting和随机森林是应用最广泛的三类集成学习算法。
用户1075469
2022/03/04
5210
第8章 集成学习 笔记
R语言实现神经网络预测股票实例数据分析可视化
因此,我们使用神经网络来解决分类问题。通过分类,我们指的是按类别对数据进行分类的分类。例如,水果可分为苹果,香蕉,橙等。
拓端
2025/02/28
670
R语言实现神经网络预测股票实例数据分析可视化
第7章 模型评估 笔记
trainControl中可以设置重采样的参数,指定boot\boot632\cv\repeatdcv\LOOCV\LGOCV\non\oob\adaptive_cv\adaptive_boot\adaptive_LGOCV等。
用户1075469
2022/03/04
8210
第7章 模型评估 笔记
k折交叉验证(R语言)
“ 机器学习中需要把数据分为训练集和测试集,因此如何划分训练集和测试集就成为影响模型效果的重要因素。本文介绍一种常用的划分最优训练集和测试集的方法——k折交叉验证。” k折交叉验证 K折交叉验证(k-fold cross-validation)首先将所有数据分割成K个子样本,不重复的选取其中一个子样本作为测试集,其他K-1个样本用来训练。共重复K次,平均K次的结果或者使用其它指标,最终得到一个单一估测。 这个方法的优势在于,保证每个子样本都参与训练且都被测试,降低泛化误差。其中,10折交叉验证是最常用的。
三猫
2018/04/10
6.9K0
k折交叉验证(R语言)
独家 | R语言中K邻近算法的初学者指南:从菜鸟到大神(附代码&链接)
在机器学习的世界里,我发现K邻近算法(KNN)分类器是最直观、最容易上手的,甚至不需要引入任何数学符号。
数据派THU
2020/02/20
1.3K0
独家 | R语言中K邻近算法的初学者指南:从菜鸟到大神(附代码&链接)
几种交叉验证(cross validation)方式的比较
模型评价的目的:通过模型评价,我们知道当前训练模型的好坏,泛化能力如何?从而知道是否可以应用在解决问题上,如果不行,那又是哪里出了问题? train_test_split 在分类问题中,我们通常通过对训练集进行train_test_split,划分成train 和test 两部分,其中train用来训练模型,test用来评估模型,模型通过fit方法从train数据集中学习,然后调用score方法在test集上进行评估,打分;从分数上我们可以知道 模型当前的训练水平如何。 from sklearn.da
用户1631856
2018/04/12
5.8K0
几种交叉验证(cross validation)方式的比较
K-fold cross validation K-fold交叉验证
In this recipe, we'll create, quite possibly, the most important post-model validation exercise—cross validation. We'll talk about k-fold cross validation in this recipe. There are several varieties of cross validation, each with slightly different randomization schemes.K-fold is perhaps one of the most well-known randomization schemes.
到不了的都叫做远方
2019/12/09
7620
cross_validate和KFold做Cross-validation的区别
一年又快要过去了,这篇本来是要新年发的文章,还好赶在农历新年前发了。想想今年也写了不少的字,也看到了不少机器学习公号从干货到恰饭的转变,有过一些困惑,甚至到了质疑意义本身。
木羊
2022/04/11
8400
R 交叉验证①
什么是交叉验证?在机器学习中,交叉验证是一种重新采样的方法,用于模型评估,以避免在同一数据集上测试模型。交叉验证的概念实际上很简单:我们可以将数据随机分为训练和测试数据集,而不是使用整个数据集来训练和测试相同的数据。交叉验证方法有几种类型LOOCV - leave -one- out交叉验证,holdout方法,k - fold交叉验证。 K折交叉验证(k-fold cross-validation)首先将所有数据分割成K个子样本,不重复的选取其中一个子样本作为测试集,其他K-1个样本用来训练。共重复K次,
用户1359560
2018/08/27
8290
R语言机器学习caret-08:过滤法
首先要理解过滤法,其实很简单,就是在建立模型前先根据一些标准把一些变量过滤掉,然后再建模。
医学和生信笔记
2023/08/30
2840
R语言机器学习caret-08:过滤法
基于机器学习的临床决策支持
声明:本文示例来自于GitHub用户vkasojhaa的项目,一切权利归其所有,此处仅是自己学习分享。
DrugAI
2021/01/28
5020
R语言实现支持向量机(SVM)
支持向量机(Support Vector Machine,SVM)是Cortes和Vapnik于1995年首先提出的,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中。支持向量机方法是建立在统计学习理论的VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力。目前使用广泛的SVM实现工具是libsvm,其不仅集成在很多统计软件例如R,PYTHON等,还可以直接在Linux以及Windows下运行。
一粒沙
2019/07/31
9.4K0
R语言第六章机器学习①R中的逐步回归要点
逐步回归(或逐步选择)包括在预测模型中迭代地添加和移除预测变量,以便找到数据集中的变量子集,从而产生性能最佳的模型,即降低预测误差的模型。
用户1359560
2018/12/27
3.7K0
相关推荐
R语言模拟:Bias Variance Decomposition
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验