我正在使用线性回归模型,并希望手动计算一些性能指标。我使用留一法交叉验证(LOOCV)分割了我的数据。
以下R代码可以得到我想要的结果,但由于我在LOOCV中使用了for循环,所以花费了很长时间。
有没有一种方法可以使用R中的apply函数族重写我的代码,使其运行得更快?
数据集是从这里上传的
wdbc <- read_excel("Folds5x2_pp.xlsx") wdbc[] <- lapply(wdbc, scale) dim(wdbc)9568 5 head(wdbc)1 -0.629 -0.987 1.82 -0.00952 0.5212 0.742 0.681 1.14 -0.975 -0.5863 -1.95 -1.17 -0.185 1.29 2.00 4 0.162 0.237 -0.508 0.228 -0.4625 -1.19 -1.32 -0.678 1.60 1.14 6 0.888 0.404 -0.173 -0.996 -0.627fitted_value <- rep(0,nrow(wdbc))for(i in 1:nrow(wdbc)){test<-wdbc[i,]training<-wdbc[-i,]m=lad(PE ~ ., data=training, method="BR")co.data = coef(m)x = cbind(1, as.matrix(test[, !(colnames(test) %in% "PE")]))fitted_value[i] <- x %*% co.data }R2<-(cor(wdbc$PE,fitted_value)^2) SAD<-sum(abs(wdbc$PE-fitted_value))c(round(SAD,2) ,round(R2,2))
注意1
问题中使用的数据仅用于解释,因为在我的项目中有很多高维数据集。
编辑
根据@Dominic van Essen的回答,我使用了来自parallel
包的parSapply
函数的以下R代码,但它比for循环花费的时间更长。
library(parallel)mycluster=makeCluster(detectCores()-1) wdbc <- read_excel("Folds5x2_pp.xlsx") wdbc[] <- lapply(wdbc, scale)clusterExport(mycluster,c("lad","wdbc")) fitted_value = parSapply(mycluster,seq_len(nrow(wdbc)),function(i) { for(i in 1:nrow(wdbc)){ test<-wdbc[i,] training<-wdbc[-i,] m=lad(PE ~ ., data=training, method="BR") co.data = coef(m) x = cbind(1, as.matrix(test[, !(colnames(test) %in% "PE")])) } return (x %*% co.data)})
注意2
我有8个核心,我的数据集中“PE”是因变量。
回答:
你可以轻松地使用sapply
代替for...
重写你的循环,尽管正如bzki评论的,这本身并不会加速你的代码:
# sapply版本:fitted_value = sapply(seq_len(nrow(wdbc)),function(i) { # 把所有这些东西放在这儿 # ... return (x %*% co.data)})
然而,如果你的电脑有多个核心可用,或者更好的是,你可以访问有许多处理器的服务器,那么sapply
循环可以很容易地使用’parallel’包中的parSapply
并行化,如下例所示:
# 慢的sapply循环(花费12秒):data=123answer = sapply(1:12,function(i) { Sys.sleep(1) return(data+i)})# 更快的并行版本(在我的4核笔记本上花费4秒):library(parallel)mycluster=makeCluster(detectCores()-1) # 留一个核心给系统使用 data=123clusterExport(mycluster,"data") # 指定应该在并行函数中可用的变量answer = parSapply(mycluster,1:12,function(i) { Sys.sleep(1) return(data+i)})stopCluster(mycluster)