Lovetoken

저는 개발 취향을 가진 데이터 분석가 Jr. 입니다.

Navigation
 » Home
 » About Me
 » Github

R에서 caret package 를 이용한 데이터 학습 간편화 전략

23 Apr 2017 » R, MachineLearning



기계학습(Machine Learning) 에서 기법이 무엇이 되든, 어떤 알고리즘을 사용할 것이든 공통으로 필요한 과정은 “Learning” 즉 “학습”이다.
학습의 대상은 전통적으로 훈련데이터(Training dataset)이고, 훈련데이터를 학습시키는 아주 다양한 방법들이 존재한다.
방법별로 원리와 특징 및 색깔이 다르며, 무엇보다 워낙 다양한 방법들이 존재하기 때문에 아무리 많이 공부를 한 사람이라 한들 모든 알고리즘을 아는것이 한계가 있다고 생각한다.
때문에 무엇을 채택해서 어느 정도의 파라미터값을 부여해야 알맞은 모델을 만들 수 있을지 현실적인 문제에 부딪히게 된다.

R에서 배포되고 있는 머신러닝 관련 패키지의 개수는 CRAN Task View: Machine Learning & Statistical Learning만을 보아도 수십개가 된다.
이 패키지들을 모두 하나하나 실행해서 상황에 맞는 모델링을 하기 위해 비교실험을 해보는 것도 가능할 것이다.
하지만 패키지별로 사용방식이 많이 다를 수 있어 이를 인지하는데도 많은 시간이 걸리고, 비교해보고 싶은 알고리즘의 패키지를 찾아 설치하고 로드하는 것 마저 부담으로 다가올 수 있겠다.

이러한 상황에서 caret 패키지는 예측모델을 만들기 위한 데이터 학습 시 간편한 함수를 제공해 준다.
특히 금일1기준 242개의 머신러닝 알고리즘을 표준화된 인터페이스를 통해 테스트 해 볼 수 있도록 준비가 되어 있고,
이에 대해서 다양한 파라미터 시나리오를 구성해 손쉽게 튜닝해주고 변수의 중요도를 측정해준다.
사용자는 편리한 훈련데이터의 학습을 통해 적절한 알고리즘 선택 의사결정에 도움을 받을 수 있다.

이러한 기대효과를 가진 caret package 에 대해 소개하는 시간을 가져보도록 하겠다.



caret 패키지의 명칭은 “Classification And REgression Training” 의 앞글자를 따와 명명되었다.
주 관심 대상이 되는 종속변수(예측변수)가 명목형 변수라면 “Classification”, 연속형 변수라면 “Regression” 으로 갈피를 잡아 “Training” 을 하게 될 텐데, 이 과정을 caret 패키지를 이용해 코딩해 본 가장 간단한 예제로 시작해 보겠다.

library(tidyverse) # for tidy tools (pipe operation, tibble, etc..)
library(caret)

set.seed(1234) # for reproducibility

data(Sonar, package = "mlbench")
Sonar <- Sonar %>% tbl_df
Sonar
## # A tibble: 208 x 61
##        V1     V2     V3     V4     V5     V6     V7     V8     V9    V10
## *   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
## 1  0.0200 0.0371 0.0428 0.0207 0.0954 0.0986 0.1539 0.1601 0.3109 0.2111
## 2  0.0453 0.0523 0.0843 0.0689 0.1183 0.2583 0.2156 0.3481 0.3337 0.2872
## 3  0.0262 0.0582 0.1099 0.1083 0.0974 0.2280 0.2431 0.3771 0.5598 0.6194
## 4  0.0100 0.0171 0.0623 0.0205 0.0205 0.0368 0.1098 0.1276 0.0598 0.1264
## 5  0.0762 0.0666 0.0481 0.0394 0.0590 0.0649 0.1209 0.2467 0.3564 0.4459
## 6  0.0286 0.0453 0.0277 0.0174 0.0384 0.0990 0.1201 0.1833 0.2105 0.3039
## 7  0.0317 0.0956 0.1321 0.1408 0.1674 0.1710 0.0731 0.1401 0.2083 0.3513
## 8  0.0519 0.0548 0.0842 0.0319 0.1158 0.0922 0.1027 0.0613 0.1465 0.2838
## 9  0.0223 0.0375 0.0484 0.0475 0.0647 0.0591 0.0753 0.0098 0.0684 0.1487
## 10 0.0164 0.0173 0.0347 0.0070 0.0187 0.0671 0.1056 0.0697 0.0962 0.0251
## # ... with 198 more rows, and 51 more variables: V11 <dbl>, V12 <dbl>,
## #   V13 <dbl>, V14 <dbl>, V15 <dbl>, V16 <dbl>, V17 <dbl>, V18 <dbl>,
## #   V19 <dbl>, V20 <dbl>, V21 <dbl>, V22 <dbl>, V23 <dbl>, V24 <dbl>,
## #   V25 <dbl>, V26 <dbl>, V27 <dbl>, V28 <dbl>, V29 <dbl>, V30 <dbl>,
## #   V31 <dbl>, V32 <dbl>, V33 <dbl>, V34 <dbl>, V35 <dbl>, V36 <dbl>,
## #   V37 <dbl>, V38 <dbl>, V39 <dbl>, V40 <dbl>, V41 <dbl>, V42 <dbl>,
## #   V43 <dbl>, V44 <dbl>, V45 <dbl>, V46 <dbl>, V47 <dbl>, V48 <dbl>,
## #   V49 <dbl>, V50 <dbl>, V51 <dbl>, V52 <dbl>, V53 <dbl>, V54 <dbl>,
## #   V55 <dbl>, V56 <dbl>, V57 <dbl>, V58 <dbl>, V59 <dbl>, V60 <dbl>,
## #   Class <fctr>

예제에 사용할 데이터셋은 mlbench::Sonar 을 이용해보겠으며 예측대상변수는 Class 라는 명칭의 명목형으로 M, R 2개의 이분값이 담겨있다.
이를 예측하는 다양한 모델을 만들어 볼 것이다.



createDataPartition() 함수

첫번째로 훈련데이터셋(Training dataset)과 테스트데이터셋(Test dataset)을 나누어 추후에 모델평가에 이용할 준비를 해보겠다. 비율은 70%를 훈련데이터셋에 배정하겠다.
sample() 함수를 이용해 훈련데이터셋과 테스트데이터셋의 파티셔닝을 해 볼 수 있지만

indexTrain <- sample(1:nrow(Sonar), round(nrow(Sonar) * .7))
training <- Sonar[ indexTrain, ]
testing  <- Sonar[-indexTrain, ]

caret 패키지에 있는 createDataPartition() 함수를 이용해 볼 수도 있다.
이 함수에는 p 인자가 있어 특정비율로 파티셔닝할 때 편하다.
또한 위의 예제코드 sample() 함수를 이용할 때는 완전무작위추출(SRS; Simple Random Sampling) 이 되기 때문에 종속변수의 요인별 비율을 고려하지 않고 무작위 샘플링이 되지만, createDataPartition() 함수를 이용할 경우 종속변수의 요인별 비율만큼 층화랜덤추출을 기본적으로 지원하기 때문에 안전하고 요긴하다.
단 반환되는 타입이 기본적으로 list 이므로 list 인자값을 FALSE로 해 보았다.

indexTrain <- createDataPartition(Sonar$Class, p = .7, list = F)
training <- Sonar[ indexTrain, ]
testing  <- Sonar[-indexTrain, ]

7:3 비율만큼 잘 파티셔닝이 되어있는지 확인해 보면

training
## # A tibble: 148 x 61
##        V1     V2     V3     V4     V5     V6     V7     V8     V9    V10
##     <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
## 1  0.0262 0.0582 0.1099 0.1083 0.0974 0.2280 0.2431 0.3771 0.5598 0.6194
## 2  0.0100 0.0171 0.0623 0.0205 0.0205 0.0368 0.1098 0.1276 0.0598 0.1264
## 3  0.0286 0.0453 0.0277 0.0174 0.0384 0.0990 0.1201 0.1833 0.2105 0.3039
## 4  0.0519 0.0548 0.0842 0.0319 0.1158 0.0922 0.1027 0.0613 0.1465 0.2838
## 5  0.0223 0.0375 0.0484 0.0475 0.0647 0.0591 0.0753 0.0098 0.0684 0.1487
## 6  0.0164 0.0173 0.0347 0.0070 0.0187 0.0671 0.1056 0.0697 0.0962 0.0251
## 7  0.0039 0.0063 0.0152 0.0336 0.0310 0.0284 0.0396 0.0272 0.0323 0.0452
## 8  0.0123 0.0309 0.0169 0.0313 0.0358 0.0102 0.0182 0.0579 0.1122 0.0835
## 9  0.0090 0.0062 0.0253 0.0489 0.1197 0.1589 0.1392 0.0987 0.0955 0.1895
## 10 0.0298 0.0615 0.0650 0.0921 0.1615 0.2294 0.2176 0.2033 0.1459 0.0852
## # ... with 138 more rows, and 51 more variables: V11 <dbl>, V12 <dbl>,
## #   V13 <dbl>, V14 <dbl>, V15 <dbl>, V16 <dbl>, V17 <dbl>, V18 <dbl>,
## #   V19 <dbl>, V20 <dbl>, V21 <dbl>, V22 <dbl>, V23 <dbl>, V24 <dbl>,
## #   V25 <dbl>, V26 <dbl>, V27 <dbl>, V28 <dbl>, V29 <dbl>, V30 <dbl>,
## #   V31 <dbl>, V32 <dbl>, V33 <dbl>, V34 <dbl>, V35 <dbl>, V36 <dbl>,
## #   V37 <dbl>, V38 <dbl>, V39 <dbl>, V40 <dbl>, V41 <dbl>, V42 <dbl>,
## #   V43 <dbl>, V44 <dbl>, V45 <dbl>, V46 <dbl>, V47 <dbl>, V48 <dbl>,
## #   V49 <dbl>, V50 <dbl>, V51 <dbl>, V52 <dbl>, V53 <dbl>, V54 <dbl>,
## #   V55 <dbl>, V56 <dbl>, V57 <dbl>, V58 <dbl>, V59 <dbl>, V60 <dbl>,
## #   Class <fctr>
testing
## # A tibble: 60 x 61
##        V1     V2     V3     V4     V5     V6     V7     V8     V9    V10
##     <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
## 1  0.0200 0.0371 0.0428 0.0207 0.0954 0.0986 0.1539 0.1601 0.3109 0.2111
## 2  0.0453 0.0523 0.0843 0.0689 0.1183 0.2583 0.2156 0.3481 0.3337 0.2872
## 3  0.0762 0.0666 0.0481 0.0394 0.0590 0.0649 0.1209 0.2467 0.3564 0.4459
## 4  0.0317 0.0956 0.1321 0.1408 0.1674 0.1710 0.0731 0.1401 0.2083 0.3513
## 5  0.0079 0.0086 0.0055 0.0250 0.0344 0.0546 0.0528 0.0958 0.1009 0.1240
## 6  0.0124 0.0433 0.0604 0.0449 0.0597 0.0355 0.0531 0.0343 0.1052 0.2120
## 7  0.0126 0.0149 0.0641 0.1732 0.2565 0.2559 0.2947 0.4110 0.4983 0.5920
## 8  0.0473 0.0509 0.0819 0.1252 0.1783 0.3070 0.3008 0.2362 0.3830 0.3759
## 9  0.0099 0.0484 0.0299 0.0297 0.0652 0.1077 0.2363 0.2385 0.0075 0.1882
## 10 0.0151 0.0320 0.0599 0.1050 0.1163 0.1734 0.1679 0.1119 0.0889 0.1205
## # ... with 50 more rows, and 51 more variables: V11 <dbl>, V12 <dbl>,
## #   V13 <dbl>, V14 <dbl>, V15 <dbl>, V16 <dbl>, V17 <dbl>, V18 <dbl>,
## #   V19 <dbl>, V20 <dbl>, V21 <dbl>, V22 <dbl>, V23 <dbl>, V24 <dbl>,
## #   V25 <dbl>, V26 <dbl>, V27 <dbl>, V28 <dbl>, V29 <dbl>, V30 <dbl>,
## #   V31 <dbl>, V32 <dbl>, V33 <dbl>, V34 <dbl>, V35 <dbl>, V36 <dbl>,
## #   V37 <dbl>, V38 <dbl>, V39 <dbl>, V40 <dbl>, V41 <dbl>, V42 <dbl>,
## #   V43 <dbl>, V44 <dbl>, V45 <dbl>, V46 <dbl>, V47 <dbl>, V48 <dbl>,
## #   V49 <dbl>, V50 <dbl>, V51 <dbl>, V52 <dbl>, V53 <dbl>, V54 <dbl>,
## #   V55 <dbl>, V56 <dbl>, V57 <dbl>, V58 <dbl>, V59 <dbl>, V60 <dbl>,
## #   Class <fctr>

훈련데이터셋이 148개, 테스트데이터셋이 60개로 잘 나누어진 것을 볼 수 있다.



머신러닝 알고리즘별 최적의 모수를 찾기 위한 학습방법 사전 설정

K 최근접 이웃모델 즉 KNN(K-Neareast Neighbors) 을 통해 명목변수를 예측하려 한다면
그 이전에 선행되어야 할 것이 “K” 를 몇개로 설정할 것이냐이다.
랜덤포레스트(RandomForest) 를 이용하려 한다면 노드를 나눌 기준으로 고려할 변수의 개수인 “mtry” 를 얼마로 정해야 할지도 마찬가지이다.
위의 예시에서 “K”, “mtry” 와 같은 모수는 예비조사를 통해 사람이 정하거나, 데이터에 근거해 최적의 군집개수를 정하는 과정을 통해 (방법이 어떻게 되었든) 정해져야 모델링을 할 수 있다. (단 비모수적 모델링이라면 제외되는 이야기이겠다)
이처럼 알고리즘 별로 반드시 정해져야 모델링을 실시 할 수 있는 모수들을 caret package 에선 “Tuning parameters” 로 설명하고 있고, LOOCV, K-fold cross validation 등과 같은 방법을 통해서 데이터에 근거한 최적의 parameter 를 찾는 과정을 거친다.

알고리즘별로 튜닝 파라미터 개수는 달라지는데 p개의 파라미터일 경우 3P 의 그리드를 탐색하여 후보모델들을 테스트하게 된다.

예를 들면 이렇다.
KNN(K-Neareast Neighbors) 는 K 하나인 단모수이므로 31 = 3 인 3가지 K 값들을 후보로 두고 모델을 비교하게 된다.
RRLDA(Robust Regularized Linear Discriminant Analysis) 의 경우 모수의 개수가 lambda, hp, penalty 총 3개인데 33 = 27 인 27가지 후보를 비교하게 될 것이다.

3개이던 27개 이던 다수의 후보에 대해서 비교하는 방식 또한 고려대상이다.
후보의 비교방법을 K-fold cross validation 으로 한다고 할 경우 몇번을 접어 cross validation 을 할 것이냐 란 질문의 K 를 정해야 한다.
caret 패키지에선 trainControl() 함수를 통해 일관된 비교방법을 각 후보에게 통일되게 적용하여 평가할 수 있게 도와준다.

아래 코드는 10-fold cross validation 을 5번 반복하여 가장 좋은 후보의 파라미터 그리드를 찾게 해주는 일종의 장치를 만드는 코드이다.

fitControl <- trainControl(method = "repeatedcv", number = 10, repeats = 5)

이렇게 만들어진 비교방법에 대한 정보가 담겨있는 fitControl 객체는 추후에 학습 과정에서 사용하게 될 것이다.



RandomForest 로 학습시켜보기

본격적으로 훈련데이터셋을 이용해 학습을 시켜보겠다.
학습을 위한 표준화된 인터페이스는 바로 train() 함수이다.
이함수에서 method 인자만 바꿔주면 원하는 학습모델 알고리즘을 구현할 수 있게 된다.

아래 코드는 랜덤포레스트를 통해 훈련데이터셋을 학습하는 코드다.
랜덤포레스트 알고리즘을 통해 학습할 것을 method = "rf" 를 통해 선언한다.
랜덤포레스트에서 Tuning parameter 에 해당되는 “mtry” 는 10-fold cross validation 을 5번 반복하여 가장 좋게 평가된 것을 선택하는 후보채택방법인 fitControl 객체를 trControl 인자에 입력한다.
verbose 인자는 기본적으로 TRUE 로 설정되어 있는데 “mtry” 선정과정이 적나라하게 모두 출력된다.
이 출력을 막고싶었기 때문에 FALSE 로 해제하였다.

더해서 랜덤포레스트를 알고리즘을 이용하기 위한 원 소스인 randomForest 패키지 여부를 먼저 확인하는 과정이 있으므로
만약 randomForest 패키지가 없다면 설치를 시도할 것인지를 물어볼 것이다. 이럴땐 패키지를 설치하겠다는 의미인 “1”을 입력하면 설치 이후 학습을 연이어 진행한다.2

rf_fit <- train(Class ~ ., data = training, method = "rf", trControl = fitControl, verbose = F)
rf_fit
## Random Forest 
## 
## 148 samples
##  60 predictor
##   2 classes: 'M', 'R' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 133, 133, 133, 133, 133, 133, ... 
## Resampling results across tuning parameters:
## 
##   mtry  Accuracy   Kappa    
##    2    0.8401905  0.6762815
##   31    0.7969524  0.5898194
##   60    0.7793333  0.5547874
## 
## Accuracy was used to select the optimal model using  the largest value.
## The final value used for the model was mtry = 2.

mtry 후보는 2, 31, 60 개로 자동설정된 것을 볼 수 있고, 이 중 Kappa 통계량과 정확도에 의해서 mtry = 2 가 최종적으로 선정된 것을 볼 수 있다.
선정과정을 자세하게 보고 싶을 경우엔 verbose = F 를 삭제하고 실행해 보면 좋을 수도 있겠다.



테스트셋에 적용하여 정확도 확인

보통 훈련데이터셋을 이용해 모델 학습하면
바로 해보고 싶은 것이 Test dataset 에 적용시켜 영리한 모델인지를 확인해 보는 것이다.

제너릭 함수인 predict() 를 이용해 볼 수 도 있겠지만

predict(rf_fit, newdata = testing)
##  [1] M M R M R R M M R M R R R R M R R R R R R R R M M R R M M R M M M M M
## [36] M M M M M M M M M M M R M M R M M M M M M M M M M
## Levels: M R

caret package 의 confusionMatrix() 를 곁들이면 혼돈메트릭스(Confusion Matrix) 및 정확도외 다양한 통계량까지 출력된다.3

predict(rf_fit, newdata = testing) %>% confusionMatrix(testing$Class)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  M  R
##          M 30  9
##          R  3 18
##                                           
##                Accuracy : 0.8             
##                  95% CI : (0.6767, 0.8922)
##     No Information Rate : 0.55            
##     P-Value [Acc > NIR] : 4.67e-05        
##                                           
##                   Kappa : 0.5876          
##  Mcnemar's Test P-Value : 0.1489          
##                                           
##             Sensitivity : 0.9091          
##             Specificity : 0.6667          
##          Pos Pred Value : 0.7692          
##          Neg Pred Value : 0.8571          
##              Prevalence : 0.5500          
##          Detection Rate : 0.5000          
##    Detection Prevalence : 0.6500          
##       Balanced Accuracy : 0.7879          
##                                           
##        'Positive' Class : M               
## 

60개의 테스트 데이터셋 중 12개가 오분류 되어 약 80% 의 정확도를 가진 것으로 볼 수 있다.



Tuning parameters 의 그리드 조정하기

사용자 검색 그리드(custom search grid)

최적 파라미터 선정 시 탐색범위와 그리드를 수동으로 조절할 수 있다.
자동으로 3P 공식에 의해 정해진 mtry 의 후보는 2, 31, 60 로 3개가 되었다.
만약 더 많은 후보와 상대평가하고 싶을 경우 후보를 사용자가 직접 설정할 수 있다는 것이다.

아래 코드는 mtry 의 후보를 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 로 바꾸어 설정하고 이 중에서 채택해 보는 코드이다.

customGrid <- expand.grid(mtry = 1:10)
rf_fit2 <- train(Class ~ ., data = training, method = "rf", trControl = fitControl, tuneGrid = customGrid, verbose = F)

rf_fit2
## Random Forest 
## 
## 148 samples
##  60 predictor
##   2 classes: 'M', 'R' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 133, 133, 134, 133, 133, 133, ... 
## Resampling results across tuning parameters:
## 
##   mtry  Accuracy   Kappa    
##    1    0.8283810  0.6509334
##    2    0.8449524  0.6849450
##    3    0.8352381  0.6654026
##    4    0.8366667  0.6687853
##    5    0.8390476  0.6740847
##    6    0.8349524  0.6651819
##    7    0.8245714  0.6441155
##    8    0.8406667  0.6766160
##    9    0.8322857  0.6603633
##   10    0.8284762  0.6522812
## 
## Accuracy was used to select the optimal model using  the largest value.
## The final value used for the model was mtry = 2.

후보를 사용자 검색에 의해 늘려보아도 이전과 같이 mtry = 2 가 최적의 파라미터로 선정되는 것을 볼 수 있다.

랜덤 검색 그리드(random selection of tuning parameter combinations)

튜닝 파라미터의 개수가 많으면 많아질수록 탐색그리드의 개수는 지수적으로 증가하게 되고 동일한 간격의 그리드 구성으로 인해 탐색과정이 비효율적이 될 수 있다.
지금까지 튜닝 파라미터가 한개인 랜덤포레스트를 예시로 했는데 이번에는 튜닝 파라미터가 2개인 RDA(Regularized Discriminant Analysis) 를 통해 훈련을 해보겠다.
method = "rda" 를 통해 알고리즘을 RDA 로 선언할 수 있다.

rda_fit <- train(Class ~ ., data = training, method = "rda", trControl = fitControl, verbose = F)

rda_fit
## Regularized Discriminant Analysis 
## 
## 148 samples
##  60 predictor
##   2 classes: 'M', 'R' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 133, 133, 133, 133, 134, 133, ... 
## Resampling results across tuning parameters:
## 
##   gamma  lambda  Accuracy   Kappa    
##   0.0    0.0     0.5687619  0.1108443
##   0.0    0.5     0.7151429  0.4264147
##   0.0    1.0     0.7499048  0.4979435
##   0.5    0.0     0.8162857  0.6298722
##   0.5    0.5     0.8340000  0.6646203
##   0.5    1.0     0.7962857  0.5907191
##   1.0    0.0     0.6405714  0.2773524
##   1.0    0.5     0.6392381  0.2748428
##   1.0    1.0     0.6406667  0.2776946
## 
## Accuracy was used to select the optimal model using  the largest value.
## The final values used for the model were gamma = 0.5 and lambda = 0.5.

총 9개의 파라미터 조합을 비교하는 것을 볼 수 있다.
바로 위에 소개한 사용자 검색 그리드 역시 expand.grid() 함수를 이용하여 동일간격 그리드를 검색하게 될 것이다. 이와는 다르게 랜덤 검색 그리드를 이용하면 동일간격 조건을 파괴시켜 파라미터 조합을 구성할 수 도 있다.
trainControl() 함수의 search = "random" 을 통해 검색 타입을 랜덤으로 바꾼다.

fitControl <- trainControl(method = "repeatedcv", number = 10, repeats = 5, search = "random")

이후 rda_fit2 라는 객체이름으로 학습을 다시 시도하고 저장해 본다.

rda_fit2 <- train(Class ~ ., data = training, method = "rda", trControl = fitControl, verbose = F)
rda_fit2
## Regularized Discriminant Analysis 
## 
## 148 samples
##  60 predictor
##   2 classes: 'M', 'R' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 134, 133, 134, 133, 133, 133, ... 
## Resampling results across tuning parameters:
## 
##   gamma      lambda      Accuracy   Kappa    
##   0.1905631  0.09127881  0.8182857  0.6359082
##   0.4408472  0.90947514  0.8528571  0.7038502
##   0.5510134  0.81992551  0.8500952  0.6971829
## 
## Accuracy was used to select the optimal model using  the largest value.
## The final values used for the model were gamma = 0.4408472 and lambda
##  = 0.9094751.

튜닝파라미터가 gamma, lambda 2개인데 검색타입을 랜덤으로 바꾸는 순간 3P 공식으로 후보군을 설정하지 않는 것을 확인할 수 있다.
수동으로 튜닝파라미터 조합개수를 늘려볼 필요가 있다. 이땐 train() 함수의 tuneLength 인자를 이용하면 된다.

rda_fit2 <- train(Class ~ ., data = training, method = "rda", trControl = fitControl, tuneLength = 50, verbose = F)
rda_fit2
## Regularized Discriminant Analysis 
## 
## 148 samples
##  60 predictor
##   2 classes: 'M', 'R' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 5 times) 
## Summary of sample sizes: 133, 133, 133, 133, 134, 133, ... 
## Resampling results across tuning parameters:
## 
##   gamma       lambda       Accuracy   Kappa    
##   0.02467175  0.046240696  0.7835238  0.5655217
##   0.04621138  0.002756874  0.7919048  0.5824003
##   0.07368577  0.095874564  0.8066667  0.6118768
##   0.07701965  0.222859888  0.8202857  0.6398213
##   0.08188038  0.929917497  0.8123810  0.6225995
##   0.08238852  0.477012957  0.8337143  0.6662831
##   0.08304677  0.278592744  0.8242857  0.6477351
##   0.13057207  0.394850662  0.8407619  0.6801815
##   0.16005396  0.740609627  0.8583810  0.7147504
##   0.16216482  0.825921020  0.8475238  0.6931098
##   0.17577373  0.014122051  0.8121905  0.6232475
##   0.18138144  0.343863922  0.8367619  0.6723626
##   0.19299614  0.250964919  0.8272381  0.6530806
##   0.21154934  0.924441815  0.8380952  0.6743253
##   0.29112614  0.062553048  0.8165714  0.6318989
##   0.32592688  0.815187029  0.8491429  0.6957937
##   0.33401985  0.355391729  0.8343810  0.6667045
##   0.33579572  0.585321935  0.8450476  0.6877346
##   0.38974907  0.595071037  0.8462857  0.6901836
##   0.43134665  0.053143749  0.8057143  0.6091455
##   0.46238233  0.225248311  0.8180952  0.6334203
##   0.48010298  0.220008595  0.8167619  0.6308603
##   0.52875129  0.900502936  0.8369524  0.6717790
##   0.59418161  0.835826412  0.8410476  0.6796135
##   0.64002373  0.715450695  0.8450476  0.6871024
##   0.66951286  0.080254850  0.8084762  0.6133645
##   0.66992710  0.557613578  0.8411429  0.6791014
##   0.68394252  0.120018550  0.8085714  0.6136620
##   0.70021389  0.623248231  0.8423810  0.6819366
##   0.70083494  0.075418255  0.8072381  0.6108154
##   0.71019128  0.776717800  0.8287619  0.6548209
##   0.72006479  0.588846389  0.8301905  0.6573055
##   0.73698825  0.234913379  0.8139048  0.6242272
##   0.74356291  0.148414826  0.8139048  0.6242293
##   0.75140091  0.109355597  0.8112381  0.6189670
##   0.75224234  0.263593657  0.8179048  0.6324297
##   0.76679423  0.973216361  0.7871429  0.5722820
##   0.79372463  0.790550417  0.8045714  0.6062931
##   0.82214953  0.130020319  0.8098095  0.6156629
##   0.82467612  0.550611505  0.8059048  0.6081189
##   0.82612455  0.693889297  0.7966667  0.5900626
##   0.84879017  0.495823009  0.7993333  0.5949617
##   0.85219803  0.931135875  0.7571429  0.5118228
##   0.86055616  0.314226715  0.8045714  0.6050836
##   0.86385220  0.089582003  0.7966667  0.5883829
##   0.87890898  0.058559475  0.7939048  0.5827761
##   0.89994468  0.677635454  0.7641905  0.5254671
##   0.93039376  0.101246271  0.7522857  0.5002045
##   0.93660375  0.971543712  0.7182857  0.4340252
##   0.95149425  0.689020876  0.7141905  0.4257570
## 
## Accuracy was used to select the optimal model using  the largest value.
## The final values used for the model were gamma = 0.160054 and lambda
##  = 0.7406096.

tuneLength = 50 로 설정해본 결과이다.
기본 그리드 검색방법에 비교해 보면 채택된 파라미터의 값이 소수점이 더 많아져 자연스럽게 정밀해 진 것을 확인할 수 있다.
이처럼 튜닝파라미터를 랜덤하게 50개로 설정하여 조금 더 융통성 있는 최적의 파라미터 튜닝 방법을 고려해 볼 수도 있겠다.



병렬처리(Parallel Processing)

병렬처리를 통해 빠른 탐색 전략을 취할 수 있다.
doMC 패키지와의 연계를 지원하는 caret 패키지는 학습 시 생기는 많은 연산을 병렬처리를 통해 시간 비용을 절감시킬 수 있다. (단 doMC package 는 Unix 계열 머신에서 사용이 가능하다) 특히 튜닝파라미터의 조합 수가 많으면 많을수록 병렬처리는 많은 효용이 있을 것이다.

필요에 따라 doMC 패키지를 설치하고 로드한다.

# install.packages("doMC")
library("doMC")

doMC 패키지를 로드하면 getDoParWorkers() 를 통해 현재 활성화된 코어수를 확인할 수 있다.

getDoParWorkers() # default cores count
## [1] 1

기본적으론 세팅 이전엔 1코어임을 확인할 수 있다.

time <- system.time({
  train(Class ~ ., data = training, method = "gbm", trControl = fitControl, verbose = F)
})
time
##    user  system elapsed 
## 218.508   1.495 221.734

이때 GBM(Stochastic Gradient Boosting Model)알고리즘으로 학습에 소요되는 시간은 222 초 내외이다.

이번에는 registerDoMC() 함수를 이용해 코어수를 2개로 늘린 후 학습에 소요되는 시간을 비교해보자.

registerDoMC(cores = 2)
getDoParWorkers()
## [1] 2
time <- system.time({
  train(Class ~ ., data = training, method = "gbm", trControl = fitControl, verbose = F)
})
time
##    user  system elapsed 
##   0.595   0.067  44.684

이때 학습에 소요되는 시간은 45 초 내외이다.
확실히 소요시간이 줄어든 것을 볼 수 있다.



Reference


  1. 2017-04-23 기준으로 글이 작성 및 수정 되었다↩︎

  2. 1: yes, 2: no↩︎

  3. 예제가 Classification 일때 이므로 Regression 일때는 논외다↩︎