歡迎大家關(guān)注我的公眾號:一只勤奮的科研喵
N次K折交叉驗證
目 錄
- K折交叉驗證簡介
- R語言N次K折交叉驗證
- 不同K取值的比較
1. 交叉驗證基本介紹
通常在建立模型后需要使用外部進行驗證,以評估模型的外部可用性。然而,獲取外部數(shù)據(jù)并不容易,這時交叉驗證(Cross Validation)則是一種較好的可替代方案。交叉驗證的方法很多,這里我們介紹最常用的k折交叉驗證。
簡單解釋一下:
- 假如原始數(shù)據(jù)為100例患者,建模后我們使用K折交叉驗證(K一般取3-10折)。
- 若取K=10,則:將原始數(shù)據(jù)分為10份(K值):
- 9份做訓(xùn)練,1份做驗證,這樣循環(huán)10次(因為這樣的組合有10種)。
- 取10次評價指標的平均值(如AUC值)作為模型的驗證結(jié)果。
即【數(shù)據(jù)分為K個子集,1個子集做驗證,K-1個子集做訓(xùn)練,這樣的取法有K種,所以會產(chǎn)生K個新數(shù)據(jù)集(訓(xùn)練集+訓(xùn)練集)。我們進行K次訓(xùn)練和驗證得到的平均評價指標可能較為準確
為了保證數(shù)據(jù)分割的影響,目前的k折交叉驗證一般會進行多次重復(fù)(200-1000次)。即進行200次的10折交叉驗證。這樣做出的結(jié)果可能會更加準確。
如文獻所示:
參考文獻: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包和數(shù)據(jù)
library(caret)#做交叉驗證用
library(pROC)#畫ROC曲線用
#清理運行環(huán)境
rm(list = ls())
#載入R包
aa<- read.csv('交叉驗證示例.csv')
#查看變量性質(zhì)
str(aa)
#批量數(shù)值轉(zhuǎn)因子
for (i in names(aa)[c(4:9)]){aa[,i] <- as.factor(aa[,i])}
#再次檢查變量性質(zhì)
str(aa)
- 載入數(shù)據(jù)后查看數(shù)據(jù)類型、有無缺項等是做數(shù)據(jù)分析很重要的一步,很大一部分錯誤都是原始數(shù)據(jù)轉(zhuǎn)換出錯造成的。
- 分類變量是factor形式而不是num/int
2.png
2-1 數(shù)據(jù)分割(K折)
#設(shè)置隨機種子,使數(shù)據(jù)分割可重復(fù)
set.seed(1)
#多次K折交叉驗證,如5折400次交叉驗證
folds <-createMultiFolds(y=aa$status,k=5,times=400)
#folds會產(chǎn)生5*400=2000個數(shù)據(jù)組合
#取fold 1數(shù)據(jù)為訓(xùn)練集,
train <- aa[folds[[1]],]
#其余為驗證集
test <- aa[-folds[[1]],]
3.png
- 可以發(fā)現(xiàn),Rstudio右邊生成了2000個數(shù)據(jù)集是5折交叉驗證重復(fù)的400次。
- 訓(xùn)練集310或311人,滿足K-1組人做訓(xùn)練,1組做驗證
2-2 取1個數(shù)據(jù)集做一次訓(xùn)練和驗證
#構(gòu)建邏輯回歸模型
model<-glm(status~age+n+hr+lvi+g+rt,
family = binomial(link=logit),
data=train )
#驗證隊列做預(yù)測
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值
上述過程重復(fù)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]],] #剩下的數(shù)據(jù)作為訓(xùn)練集
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. 不同交叉驗證比較
結(jié)果
- 無交叉驗證AUC值:0.906
- 400次5折交叉驗證平均AUC :0.89047
- 200次10折交叉驗證平均AUC:0.89092
- 單純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次批量訓(xùn)練與驗證
#做成循環(huán)
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次批量訓(xùn)練與驗證
#做成循環(huán)
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)
歡迎大家關(guān)注我的公眾號:一只勤奮的科研喵
相關(guān)專題:
R語言 | X年N次K折交叉驗證
R語言 | 多指標N次K折交叉驗證
一只勤奮的科研喵