ランダムフォレストをループすることによる大量メモリ消費の解決策

概要

データ中に目的変数が複数あり、それぞれについてランダムフォレストを用いてモデルを作成しようとすると方法によってメモリ消費がかなり異なる。

  1. 関数内でforループを利用する方法
  2. forループで関数自体をループさせる方法

結論は1.を利用すると大変なメモリ消費になってしまうが、2.を用いると解決することができる。

詳細

1.関数内でforループを利用する方法

randomparallel <- function(){
    cores<-detectCores()
    cl<-makeCluster(cores,type="PSOCK")
    invisible(clusterEvalQ(
        cl,{
            library(randomForest)
            set.seed(123)
        }))

    clusterExport(cl,"i")
    clusterExport(cl,"data")
    clusterExport(cl,"newdata")
    clusterSetRNGStream(cl)
    
    for( i in 1:6 ){
        res.pa<-parLapply(cl,rep(250,cores),function(ntree) randomForest(formula(paste(colnames(data)[i],".",sep="~")),data,ntree=ntree))
        res.all<-do.call("combine",res.pa)
        pre.model<-predict(res.all,newdata=newdata[randomcol],type="class")
        submit[,i]<-pre.model
    }

    stopCluster(cl)
}
randomparallel()

randomforest実行6ループ目の時のメモリ消費量parallel2.png

  • 毎回のループのrandomforest()で利用したメモリが関数から抜け出すまで解放されないことが原因と考えられる。

2.forループで関数自体をループさせる方法

randomparallel <- function(){
    cores<-detectCores()
    cl<-makeCluster(cores,type="PSOCK")
    invisible(clusterEvalQ(
        cl,{
            library(randomForest)
            set.seed(123)
        }))

    clusterExport(cl,"i")
    clusterExport(cl,"data")
    clusterExport(cl,"newdata")
    clusterSetRNGStream(cl)

    res.pa<-parLapply(cl,rep(250,cores),function(ntree) randomForest(formula(paste(colnames(data)[i],".",sep="~")),data,ntree=ntree))
    res.all<-do.call("combine",res.pa)
    pre.model<-predict(res.all,newdata=newdata[randomcol],type="class")
    submit[,i]<-pre.model

    stopCluster(cl)
}
for( i in 2:6 ){
    randomparallel()
}

randomforest実行6ループ目の時のメモリ消費量parallel1.png

  • randomforest()で利用されるメモリがループの度に解放されていると考えられる。

参考資料