Boosting Tree를 이용한 특징 추출

Tree기반의 Boosting 알고리즘을 일반적으로 GBDT라고 이야기한다. 사실 필자가 Boosting기법을 실무에 직접 활용한건 약 9년전 Yahoo!에서 였는데, 당시 지금 모델링하는 방식과는 다른 무식한 방법으로 모델링하고 적용하기를 반복하면서 깊이있는 활용과 이해는 하지 못했던 아쉬움이 있었다. 하지만 다시 그 진가를 확인하고 있는 순간이 왔고 모델링 뿐만 아니라 속성 추출에도 활용 가능한 팔방미인이라는 것을 최근에 알게 되면서 다소 방법론 자체에 고무되어 있는 상황이다.

참고로 Boosting기법에 대한 설명은 이전 포스팅을 참고하기 바란다.

실직적인 의미에서 데이터 분석하고는 거리가 조금 있다고 생각하고 있는(문제의 맥락과 변수 자체의 의미해석과 타 변수와의 관련성을 파악해서 실제 의사결정에 도움을 주는 것을 일반적인 데이터 분석이라 생각하는데, 대회의 경우 성능 목적 자체에만 집중하기 때문이다) 머신러닝 대회인 Kaggle을 보면 2015년도 들어오면서 Boosting 방법이 randomForest와 SVM에 이어서 새롭게 부각되고 있다는 느낌을 많이 받았고 R의 gbm이나 Python 유저들이 즐겨 사용하는 xgboost와 같은 편리한 패키지와 caret과 같은 모델 튜닝 프레임웍의 도움으로 그 활용 범위는 더 넓어지고 이미 대중적인 알고리즘이 되었다는 느낌을 많이 받았다.

불과 몇일전에 팀분에게 소개받은 xgboost의 경우 학습속도가 무지막지하게 느린 gbm에 비해 10배 이상 학습 속도의 향상을 가져온다는 것을 직접 체험하였고, 몇가지 파라메터 셋팅으로 자신만의 Learner를 구성할 수 있는 큰 장점을 가지고 있어 사용자로 하여금 유연하게 활용할 수 있는 여지를 제공해주고 있다. 예를 들면 트리를 독립적으로 생성하고 노드의 속성 선택을 랜덤하게 선택하게끔 파라메터 설정을 하게되면 randomForest 알고리즘으로 동작하게 되는 등 다양한 설정이 가능하다.

게다가 힘들게 튜닝한 gbm 파라메터를 그대로 xgboost로 활용 가능한데, 아래와 같은 파라메터 매핑을 하면 된다.

gbm xgboost
interaction.depth max.depth
n.trees nrounds
shrinkage eta

gbm의 n.minobsinnode파라메터는 대부분 튜닝 포인트에서 빠지니 핵심적인 튜닝 포인트인 위 파라메터만 정리했다.

Boosting Tree를 이용한 속성 추출

Criteo 대회의 우승 코드와 문서를 몇개 찾아볼 수 있는데, 뭐 현재로서는 일반적인 방법이라고 하는 꽤 쇼킹한 속성 추출 방식을 보여주고 있고, 실제 이 덕분에 우승까지 한 것을 볼 수 있다.
간단하게 설명하면 GBDT를 이용해 추가 속성들을 만들어주고 이들 속성과 기본 속성을 모두 별도의 모형(Factorization Machines)에 넣어서 모델링을 수행한 것이다. (이런 특징 추출 작업 + SVM 활용이 Factorization Machines 방법이지 않을까 하는 생각을 해본다)

레코드별로 추가되는 n개의 별도 속성을 만들어 주기 위해 n개의 부스팅 트리를 생성한 이후 각 트리의 leaf노드의 인덱스숫자를 속성값으로 넣어준 것이다. 이 작업으로 속성간의 interaction에 대한 변수를 직접적으로 생성하게되는 효과를 가져오게 되는 것이다. 이 속성을 GBDT features라고 이야기 하는데 이걸 그림으로 표현하며 아래와 같다.


from : https://github.com/guestwalk/kaggle-2014-criteo

개인적으로 이 방식이 시사하는 바가 큰데, 매우 sparse한 속성들에 대해서 다소 차원축소를 하는 효과를 가져오는 잇점이 있다는 것이다. 특히나 속성의 갯수가 레코드의 갯수에 비해서 많은 경우에 활용할 수 있는 유용한 기법이란 생각을 해본다.

사실 이 방식으로 GBDT를 활용하는 사례가 많아져 xgboost의 경우 leaf node의 index를 뽑아내게 옵션까지 제공하고 있는 상황인데, 아래는 관련 예제중이 하나이다.

#from https://github.com/dmlc/xgboost/blob/master/R-package/demo/predict_leaf_indices.R
library(xgboost)

#load in the agaricus dataset
data(agaricus.train, package='xgboost')
data(agaricus.test, package='xgboost')
dtrain <- xgb.DMatrix(agaricus.train$data, label = agaricus.train$label)
dtest <- xgb.DMatrix(agaricus.test$data, label = agaricus.test$label)

param <- list(max.depth=2,eta=1,silent=1,objective='binary:logistic')
watchlist <- list(eval = dtest, train = dtrain)
nround = 5

# training the model for two rounds
bst = xgb.train(param, dtrain, nround, nthread = 2, watchlist)
## [0]  eval-error:0.042831 train-error:0.046522
## [1]  eval-error:0.021726 train-error:0.022263
## [2]  eval-error:0.006207 train-error:0.007063
## [3]  eval-error:0.018001 train-error:0.015200
## [4]  eval-error:0.006207 train-error:0.007063
cat('start testing prediction from first n trees\n')
## start testing prediction from first n trees
### predict using first 2 tree
pred_with_leaf = predict(bst, dtest, ntreelimit = 2, predleaf = TRUE)
head(pred_with_leaf)
##      [,1] [,2] 
## [1,]    4    3 
## [2,]    3    3 
## [3,]    4    3 
## [4,]    4    3 
## [5,]    5    4 
## [6,]    3    3 
# by default, we predict using all the trees
pred_with_leaf = predict(bst, dtest, predleaf = TRUE)
head(pred_with_leaf)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    4    3    5    4    4
## [2,]    3    3    5    3    4
## [3,]    4    3    5    4    4
## [4,]    4    3    5    4    4
## [5,]    5    4    5    3    4
## [6,]    3    3    5    3    3

 

`Boosting`은  “too good to be true.”라는 문장이 생각이 날 정도로 성능향상이 많이 되는 경우가 있는 다소 사기적인 모형중에 하나인데, 위와 같이 새로운 속성을 추출하는 용도로 활용 가능하다는 것에 필자는 다소 충격을  받은 상황이다.  그리고 데이터를 모형을 통해 추상화 해석하여 새로운 속성을 도출하는 방식은 다소 deep learning의 그것을 보는 듯한 느낌까지 준다.

CC BY-NC 4.0 Boosting Tree를 이용한 특징 추출 by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.