読者です 読者をやめる 読者になる 読者になる

琥珀色呑んだくれ備忘録

メモとか備忘録とか

foreach+%dopar%をネストしたい

R

並列化できる評価関数があり、その調節パラメータを並列にグリッドサーチしたい。単純に考えると親のソケットクラスタから子クラスタを生成すると良いのかな、と思うがもっといい方法ないものか。

評価関数は例えば、randomForestのようなアンサンブル学習でも良いし、遺伝的アルゴリズムのような最適化でも良いし、LOOみたいなcross-validationを考えても良い。Rで簡単に書ける。

require(foreach)
require(doParallel)

eval_parallel <- function(){
  # 親ソケットクラスタ
  cl <- makeCluster(8)
  registerDoParallel(cl)
  on.exit(stopCluster(cl))

  # 子クラスタの格納用
  cl_i <-NULL

  # grid searchの条件組み合わせを列挙しておく
  conditions <- expand.grid(a=1:3, b=letters[2:7], c=c(1.1,1.7,1.9))

  foreach(i=1:NROW(conditions), .packages = c("foreach", "doParallel"), .combine = rbind) %dopar%{
    # 子クラスタ
    cl_i[[i]] <- makeCluster(11)
    registerDoParallel(cl_i[[i]])
    on.exit(stopCluster(cl_i[[i]]))

    # ハイパーパラメータのセット
    parameters <- conditions[i,]

    # iteration_sizeは弱学習器の数だったり、CVのfolding数だったり、GAの個体数だったり
    foreach(j=1:iteration_size, .combine = c) %dopar% {
      # do something
    }
  }
}

eval_parallel()

この例では親が8いて子が11づつ作られるので、8*(1+11)=96並列。親子のバランスはボトルネックを見て配分すればよい。ときどき親の割り当てぶんの確保を忘れる。
.combineがrbindとcになってるのは、このあとでrowMeansすれば平均精度を見てベストなパラメータセットを探せるcross-validationのイメージ。

on.exit()使ってるのは下記の記事から。
R の foreach で並列処理するとき on.exit() が便利 #rstatsj - Qiita

もうちょっとうまいやり方がありそうだけど、思いつかないので今はこれで凌いでいる。