This is my first time posting so hopefully I manage to get my question across in a clear and concise manner. I'm not sure this is the right place but someone on StackOverflow suggested I ask here.
I am running a cross-validation experiment which involves training a model on a subset of a data set and then validating it against the rest of the data set. This is done by randomly subsetting the data into "folds" and then running the model for each fold. This is then replicated in order to produce standard errors. This is the code I have written in R:
reps = 10
folds = 10
rep.Res<-list()
for(i in 1:reps){
#i=1
phen2<-phen
phen2$fold<-sample(1:folds,nrow(phen),replace=T)
fold.Res<-list()
for(j in 1:folds){
#j=1
print(paste(i," ",j))
phen3<-phen2
phen3[which(phen3$fold==j),2]<-NA
ETA<-list(list(X = geno_centred, model = 'BayesA'))
model <- BGLR(y = phen3[,2], ETA = ETA, nIter = 20000,
burnIn = 1500, thin=10)
model.output<-data.frame(ID = phen3[which(phen2$fold == j), 1],
PBV = as.numeric(model$yHat[which(phen2$fold == j)]),
phen = phen2[which(phen2$fold == j), 2], rep = i, fold = j)
fold.Res[[j]]<-model.output
}
rep.Res[[i]]<-do.call(rbind,fold.Res)
}
"phen" is a data frame with a a column of IDs and a column of values. For each replicate, each sample is assigned to a fold randomly. Then, for each fold individuals in the fold are given an NA value, i.e. excluded from the model.
The model is run using the Bayesian Generalised Linear Regression (BGLR) package. Unfortunately, I can't really give a reproducible example. X is a scaled centred genotype matrix of -1's, 0's and 1's (not critical for my problem here). The output of the model is then written out for each fold, and then finally for each replicate.
My question is, is it possible to vectorize these loops? Using 10 folds and 10 reps means that the model runs 100 time, at 20 000 MCMC iterations each time. This causes the system to slow down significantly before it's even half done. I know that there are many possible approaches using basic R or packages in the tidyverse suite, but I am really a bit lost with such a complex loop. I can imagine that I would try to write at least one of the loops into a function enclosing the other loop but I'm not even sure how that would work...
Again, first time posting so please let me know if I need to add anything to my question! Thanks!
Edit: Here are a small, random centred genotype matrix (X in the call to BGLR) and an accompanying phen file.
X (rows are sample IDs matching those in phen, columns are genomic locations (SNPs)):
A B C D E F G H I J K L M N O P Q R S T
1 1 1 1 -1 -1 0 -1 -1 0 1 -1 0 0 0 0 -1 0 0 1 1
2 -1 1 0 -1 0 0 1 -1 1 0 -1 1 -1 0 0 0 -1 -1 -1 -1
3 -1 -1 1 -1 0 0 1 0 0 -1 -1 0 -1 0 0 -1 1 -1 0 -1
4 0 0 -1 1 -1 0 -1 1 1 1 -1 0 0 0 1 1 -1 -1 0 1
5 1 0 1 1 0 0 1 1 0 0 -1 1 1 1 1 -1 -1 0 -1 0
6 1 -1 -1 0 1 -1 1 1 1 -1 0 0 0 -1 0 1 0 -1 -1 0
7 1 -1 -1 1 1 0 -1 1 -1 1 0 -1 1 1 -1 -1 -1 1 -1 1
8 0 1 0 1 -1 -1 0 -1 -1 -1 1 -1 0 0 0 0 0 -1 0 -1
9 -1 1 -1 -1 1 0 0 0 0 0 1 0 -1 -1 -1 0 1 -1 0 -1
10 0 0 -1 1 0 0 -1 0 -1 1 1 1 0 0 1 1 0 -1 0 0
Phen:
ID phenotype
1 1000
2 1500
3 1200
4 500
5 700
6 2000
7 1500
8 1000
9 1300
10 900
BGLR
take, and don't you expect your code to take roughly 100 times that time? I don't understand your comment This causes the system to slow down significantly before it's even half done; it seems to suggest that each iteration is slower than the previous one but I dont see anything in your code that could cause that. If your code indeed takes ~100x the time spent in a singleBGLR
call, I don't see how you can make that much faster. We can otherwise help make your code a bit cleaner/simpler if you are interested. \$\endgroup\$phen
. If it is too big or contains sensitive data, can you give a minimal random data set so we can reproduce your work? \$\endgroup\$