R语言 | N次K折交叉验证(基于逻辑回归)

欢迎大家关注我的公众号:一只勤奋的科研喵

N次K折交叉验证

目 录

  1. K折交叉验证简介
  2. R语言N次K折交叉验证
  3. 不同K取值的比较

1. 交叉验证基本介绍

通常在建立模型后需要使用外部进行验证,以评估模型的外部可用性。然而,获取外部数据并不容易,这时交叉验证(Cross Validation)则是一种较好的可替代方案。交叉验证的方法很多,这里我们介绍最常用的k折交叉验证

简单解释一下:
  • 假如原始数据为100例患者,建模后我们使用K折交叉验证(K一般取3-10折)。
  • 若取K=10,则:将原始数据分为10份(K值):
  • 9份做训练,1份做验证,这样循环10次(因为这样的组合有10种)。
  • 取10次评价指标的平均值(如AUC值)作为模型的验证结果。

即【数据分为K个子集,1个子集做验证,K-1个子集做训练,这样的取法有K种,所以会产生K个新数据集(训练集+训练集)。我们进行K次训练和验证得到的平均评价指标可能较为准确


为了保证数据分割的影响,目前的k折交叉验证一般会进行多次重复(200-1000次)。即进行200次的10折交叉验证。这样做出的结果可能会更加准确。
如文献所示:

参考文献:Alexia Iasono et al. How To Build and Interpret a Nomogram for Cancer Prognosis.png

参考文献:Development and validation of NTCP models for acute side-effects resulting from proton beam therapy of brain tumours.png

2. R语言:K折交叉验证

1.载入R包和数据

library(caret)#做交叉验证用
library(pROC)#画ROC曲线用
#清理运行环境
rm(list = ls()) 
#载入R包
aa<- read.csv('交叉验证示例.csv')
#查看变量性质
str(aa)
#批量数值转因子
for (i in names(aa)[c(4:9)]){aa[,i] <- as.factor(aa[,i])}
#再次检查变量性质
str(aa)
  • 载入数据后查看数据类型、有无缺项等是做数据分析很重要的一步,很大一部分错误都是原始数据转换出错造成的。
  • 分类变量是factor形式而不是num/int
    2.png

2-1 数据分割(K折)

#设置随机种子,使数据分割可重复
set.seed(1)
#多次K折交叉验证,如5折400次交叉验证
folds <-createMultiFolds(y=aa$status,k=5,times=400)
#folds会产生5*400=2000个数据组合
#取fold 1数据为训练集,
train <- aa[folds[[1]],]
#其余为验证集
test <- aa[-folds[[1]],]
3.png
  • 可以发现,Rstudio右边生成了2000个数据集是5折交叉验证重复的400次。
  • 训练集310或311人,满足K-1组人做训练,1组做验证

2-2 取1个数据集做一次训练和验证

#构建逻辑回归模型
model<-glm(status~age+n+hr+lvi+g+rt,
          family = binomial(link=logit), 
          data=train )
#验证队列做预测
model_pre<-predict(model,
                   type='response',
                   newdata=test)
#查看AUC值、敏感性、特异性
roc1<-roc((test$status),model_pre)
round(auc(roc1),3)
roc1$sensitivities
round(roc1$specificities,3)
#ROC可视化
plot(roc1, 
     print.auc=T, 
     auc.polygon=T, 
     auc.polygon.col="skyblue",
     grid=c(0.1, 0.2),
     grid.col=c("green", "red"), 
     max.auc.polygon=T,
     print.thres=T)

4.png

2-3 批量计算AUC值

上述过程重复2000次,得到2000个auc值,取平均值即可得到模型400次5折交叉验证的auc校准值。

#建一个放auc值的空向量
auc_value<-as.numeric()
#上述步骤2000次
for(i in 1:2000){
  train<- aa[ folds[[i]],] #folds[[i]]作为测试集
  test <- aa[-folds[[i]],] #剩下的数据作为训练集
  model<- glm(status~age+n+hr+lvi+g+rt,family=binomial(link=logit),data=train)
  model_pre<-predict(model,type='response', newdata=test)
  auc_value<- append(auc_value,as.numeric(auc(as.numeric(test[,1]),model_pre)))
}
#查看auc值分及平均auc
summary(auc_value)
mean(auc_value) 
# AUC=0.8901765



3. 不同交叉验证比较

结果

    1. 无交叉验证AUC值:0.906
    1. 400次5折交叉验证平均AUC :0.89047
    1. 200次10折交叉验证平均AUC:0.89092
    1. 单纯10折交叉验证平均AUC :0.88537
      因此交叉验证是十分必要的,推荐N次K折交叉验证

1. 400次5折交叉验证
平均AUC=0.890468(代码见上)
2. 不做交叉验证
AUC=0.906

model1<-glm(status~age+n+hr+lvi+g+rt,
            family = binomial(link = logit),
            data=aa)
model_pre1<-predict(model1,type='response')
roc2<-roc((aa$status),model_pre1);auc(roc2)

3. 200次10折交叉验证
平均AUC=0.8909152

set.seed(1)
folds <-createMultiFolds(y=aa$status,k=10,times=200)
#2000次批量训练与验证
#做成循环
auc_value<-as.numeric()
for(i in 1:2000){
  train<- aa[ folds[[i]],] 
  test <- aa[-folds[[i]],] 
  model<- glm(status~age+n+hr+lvi+g+rt,family=binomial(link=logit),data=train)
  model_pre<-predict(model,type='response', newdata=test)
  auc_value<- append(auc_value,as.numeric(auc(as.numeric(test[,1]),model_pre)))
}
mean(auc_value)

4. 单纯10折交叉验证
平均AUC=0.8853679

set.seed(1)
#单纯10折交叉验证,time=1
folds <-createMultiFolds(y=aa$status,k=10,times=1)
#10次批量训练与验证
#做成循环
auc_value<-as.numeric()
for(i in 1:10){
  train<- aa[ folds[[i]],] 
  test <- aa[-folds[[i]],] 
  model<- glm(status~age+n+hr+lvi+g+rt,
              family=binomial(link=logit),data=train)
  model_pre<-predict(model,type='response', newdata=test)
  auc_value<- append(auc_value,
                     as.numeric(auc(as.numeric(test[,1]),model_pre)))
}
mean(auc_value)

欢迎大家关注我的公众号:一只勤奋的科研喵

相关专题:

  • R语言 | X年N次K折交叉验证
  • R语言 | 多指标N次K折交叉验证
一只勤奋的科研喵
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容