foreach l oop с 300 тыс. итераций зависает в .combine время с большим использованием оперативной памяти, R - PullRequest
0 голосов
/ 10 апреля 2020

Я столкнулся с реальной проблемой при анализе моих данных. Я надеюсь, что кто-то из вас сможет мне помочь.

У меня 18 переменных и двоичный результат. Я хочу попробовать все возможные комбинации переменных (т.е. 2 ^ 18 -1 = 262'143) и для каждой из них построить три модели (Logisti c, SVM, RandomForest) и вычислить AU C .

Одна итерация длится около 10 с, и у меня довольно неплохой компьютер (12 ядер + HT, 160 ГБ ОЗУ), поэтому я реализовал следующий код для l oop (fitData - это фрейм данных со всеми ковариатами и результат)

cl <- makeCluster(15, outfile="")
registerDoParallel(cl)

clinicalSweep3 <- foreach (kei= 1:(2^(length(varNames)) -1), .combine='rbind', .packages=c('e1071','pROC','randomForest')) %dopar% {
  varNamesKei <- varNames[as.logical(intToBits(kei)[1:(length(varNames))])]
  yString <- (paste(as.integer(intToBits(kei)[1:(length(varNames))]),collapse=""))
  yLabel <- as.character(paste(varNamesKei,collapse="+"))

  covPacket <- data.frame(t(strsplit(yString,"")[[1]]))
  colnames(covPacket) <- varNames

  AUC_Logit <- NA
  AUC_SVM <- NA
  AUC_RF <- NA

  AUC_Logit2CV <- NA
  AUC_SVM2CV <- NA
  AUC_RF2CV <- NA

  predLogit <- 1:dim(fitData)[1]
  predSVM <- 1:dim(fitData)[1]
  predRF <- 1:dim(fitData)[1]
  for (k in 1:dim(fitData)[1]){
    predLogit[k] <- predict(glm(as.formula(paste("outcome ~ ", paste(varNamesKei, collapse= "+"))),data = fitData[-k,], family=binomial(link='logit')),type="response", newdata = fitData[k,,drop=F])
    predSVM[k] <-   predict(svm(as.formula(paste("outcome ~ ", paste(varNamesKei, collapse= "+"))),data = fitData[-k,], kernel = "linear", cost = 10, type = "C-classification"), newdata = as.data.frame(fitData[k,,drop=F]))
    predRF[k] <-    predict(randomForest(as.formula(paste("outcome ~ ", paste(varNamesKei, collapse= "+"))),data = fitData[-k,], ntree=100),type="prob", newdata = fitData[k,,drop=F])[2]
  }

  AUC_Logit <- auc(fitData$outcome,predLogit,direction="<", levels = c(F,T))
  AUC_SVM <- auc(fitData$outcome,predSVM,direction="<", levels = c(F,T))
  AUC_RF <- auc(fitData$outcome,predRF,direction="<", levels = c(F,T))

  predLogit <- 1:dim(fitData)[1]
  predSVM <- 1:dim(fitData)[1]
  predRF <- 1:dim(fitData)[1]
  for (k in 1:(dim(fitData)[1]/2)){
    predLogit[c(2*k-1,2*k)] <- predict(glm(as.formula(paste("outcome ~ ", paste(varNamesKei, collapse= "+"))),data = fitData[-c(2*k-1,2*k),], family=binomial(link='logit')),type="response", newdata = fitData[c(2*k-1,2*k),,drop=F])
    predSVM[c(2*k-1,2*k)] <-   predict(svm(as.formula(paste("as.numeric(outcome)-1 ~ ", paste(varNamesKei, collapse= "+"))),data = fitData[-c(2*k-1,2*k),], kernel = "linear", cost = 10, type = "eps-regression"), newdata = as.data.frame(fitData[c(2*k-1,2*k),,drop=F]))
    predRF[c(2*k-1,2*k)] <-       predict(randomForest(as.formula(paste("outcome ~ ", paste(varNamesKei, collapse= "+"))),data = fitData[-c(2*k-1,2*k),], ntree=100),type="prob", newdata = fitData[c(2*k-1,2*k),,drop=F])[,2]

  }

  AUC_Logit2CV <- auc(fitData$outcome,predLogit,direction="<", levels = c(F,T))
  AUC_SVM2CV <- auc(fitData$outcome,predSVM,direction="<", levels = c(F,T))
  AUC_RF2CV <- auc(fitData$outcome,predRF,direction="<", levels = c(F,T))

}

cat(as.character(Sys.time()),"combo",yString,"done! (",kei,")\n")

data.frame( yString, covPacket,
            AUC_Logit, AUC_SVM,AUC_RF ,
            AUC_Logit2CV, AUC_SVM2CV, AUC_RF2CV ,
            yLabel)

}

Теперь код работает без проблем около 30 часов, хотя я заметил, что объем оперативной памяти постоянно увеличивается. Вчера я решил создать область подкачки объемом 100 ГБ, и, действительно, когда последний рабочий закончил, ситуация была следующей.

RAMUsage

ЦП больше не было используется, но сеанс R все еще был заблокирован и работает. Я надеялся, что это закончится в одночасье, но сегодня утром ситуация не лучше.

enter image description here Своппинг установлен на 50.

Теперь я понял, что foreach не должен использовать с таким количеством итераций.

Теперь вопросы:

1) Должен ли я остановить и переписать весь код, вложив нормальный l oop в foreach? (около 3000 итераций в foreach * 100 в норме для). Или я должен подождать (возможно, увеличить обмен)

clinicalSweep3 <- foreach (kei1= 0:floor((2^(length(varNames)) -1)/100), .combine='rbind', .packages=c('e1071','pROC','randomForest')) %dopar% {
  for (kei2 in 1:min((2^(length(varNames)) -1) - kei1*100,100 ) ) {
    kei <- kei1*100+kei2

# РЕДАКТИРОВАТЬ: я обнаружил, что, вероятно, foreach (kei = idiv (2 ^ (length (varNames))) -1, chunks = 100), .. .) надо делать работу

2) Почему это массовое использование ОЗУ и как его избежать? (это все в основной rsession, а не в рабочих). Должен ли я запускать g c () в начале / конце каждой итерации? (по умолчанию .export = NULL не должен импортировать все в рабочих формах основного потока)

3) Почему мое ядро ​​(из Ubuntu 20.04 Desktop) недостаточно загружено? Может быть, потому что это один поток с 300 ГБ?

4) Если у вас есть предложения о том, как улучшить общую производительность кода, я буду рад их услышать!

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...