parallel model tunning with caret

caret에는 최적 모델링 파라메터를 평가해주는 train이라는 함수를 제공하고 있다. 예를 들어 randomForest의 경우에는 mtry라는 변수가 있는데, 이 변수는 트리를 생성할때 랜덤한 몇개의 변수를 후보로 사용해서 분리(split)를 할것인지를 가지고 있어야 한다. 결국 이 ‘몇개’ 라는 이 값이 튜닝 포인트인 것이다.

이를 위해서 10 cross validation 전략으로 각 파라메터 튜닝 값에 대한 10 cross validation 결과를 출력하고자 한다. 기본적인 숫자형 목적변수에 대한 평가 기준은 RMSE이다. 그러니까 가장 적은 RMSE를 가진 모델 파라메터를 선택하면 된다.

 

코드를 보면…

> library(caret)
#cross validation으로 평가 방법을 정한다.
> fitcontrol <- trainControl(method="cv")
> rf_mrty_tunning <- train(quality ~ ., data=trainset_rf[-1],trControl=fitcontrol, method="rf")

 

이 코드는 튜닝 파라메터에 2,7,13의 값을 후보로 각 10개의 모델을 생성해 RMSE를 측정하게 된다. 그러니까.. 약 30개의 모델을 파라메터 튜닝을 위해 빌드하게 된다.

생성되는데 걸리는 시간은

> rf_mrty_tunning$times
$everything
user system elapsed
1344.836 24.989 1371.436
$final
user system elapsed
48.315 0.608 48.961

약 22분, 이게 1개의 파라메터니까 그렇지 gbm같은 알고리즘은 세개의 파라메터를 튜닝하게 되는게 각각 경우의 수는 파라메터의 가능 조합에 따르기 때문에 기하급수적으로 늘어나게 된다. 그말인 즉슨, (1,2), (a,b), (A,B) 각 후보 파라메터 값이 있다고 했을때 8개의 가능 조합이 나타나게 되는데, 결국 80개의 모델을 빌드해야 된다는 이야기가 된다.

이런 일을 sequential하게 처리하게 되면 모델 파라메터 튜닝에 엄청난 시간이 걸리게 된다. 그러나 운좋게도 각 테스트는 독립적으로 수행이 가능하다. 그렇다면 parallel하게 모델을 테스트 해볼 수 있다는 이야기다.

그래서 나온 방법이 가용한 모든 core를 이용하게 하는 parallel training이다

 

doMPI를 사용해야 하는데, 리눅스 머신에서 openmpi-devel 패키지를 설치하고 아래와 같은 명령어로 Rmpi를 먼저 설치후 doMPI를 설치하면 된다. 사실 LD_LIBRARY_PATH를 설정하고 include path를 정의해주면 되는데, 귀찮에서 인스톨 패키지 코드로 넣어 버렸다.

> install.packages("Rmpi", configure.args =c("--with-Rmpi-include=/usr/lib/openmpi/1.4-gcc/include/", "--with-Rmpi-libpath=/usr/lib/openmpi/1.4-gcc/lib/", "--with-Rmpi-type=OPENMPI"))
> install.packages("doMPI")
> library(doMPI)
> cl <- startMPIcluster(2)
2 slaves are spawned successfully. 0 failed.
> registerDoMPI(cl)
> set.seed(1)
> rf_mrty_tunning_par <- train(quality ~ ., data=trainset_rf[-1],trControl=fitcontrol, method="parRF")
> closeCluster(cl)

 

위와 같이 2개의 worker를 생성하고 method=”parRF”로 해주면 parallel 한 radnomForest가 실행된다.

사실 parRF의 경우 편리하게 패키지에서 정의해준 것인데, 만일 정의되지 않은 알고리즘이라도 trainControl의 computeFunction을 parlapply와 같은 MPI 버전의 lapply함수로 재정의 해주면 된다.

결국 parallel 버전의 알고리즘 튜닝 시간은

> rf_mrty_tunning_par$times
$everything
user system elapsed
122.619 344.346 596.849
$final
user system elapsed
0.344 0.136 13.070

10분정도로 줄었는데, 2배 이상 빨라진 결과를 보여준다.

테스트 했던 클라우드 instance의 core가 2개여서 2개의 worker를 가지고 테스트 했는데, 아마 다른 분들은 코어 개수에 맞춰서 테스트 해보면 재밋는 결과를 볼 수 있지 않을까 한다.

 

사실 이번 포스팅의 동기는 예전에 hadoop을 기반으로 이런 튜닝 파라메터를 튜닝했던 경험이 있어서이다. 그 당시만 해도 훨씬 많은 튜닝 파라메터와 값들로 인해 결국 hadoop에 올려서 테스트 하고 가장 최적의 값을 선택해서 알고리즘을 적용했었다. 아마도 파라메터 값만 수십개 그리고 테스트 해보고자 하는 값들이 수십개 정도만 해도 로컬에서 parallel train만으로는 힘든 지경이 될거라 생각한다. 아마도 그때는 다시 hadoop클러스터를 이용한 파라메터 튜닝을 하고 있지 않을까 한다.

 

CC BY-NC 4.0 parallel model tunning with caret by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.