본문 바로가기

Codestates AI 부트캠프/2. Machine Learning

[머신러닝] 2-1 Tree Based Model

오늘의 주제는 tree 기반 모델로 Decision Tree와 Random Forest를 데이터에 적용해본다.

 


1. Decision Tree

 


질문을 던져 yes or no로 데이터를 분할하는 알고리즘. 나무가 가지를 뻗어나가는 모양과 비슷해 Tree라는 이름이 붙었다. 질문이나 정답을 담고있는 node와 연결선 edge로 구성된다. 위 그림으로 볼 때 node는 박스, edge는 선으로 생각하면 된다.  회귀와 분류 문제 모두에서 쓰일 수 있다. 

분류 문제에서의 결정 트리 
- 불순도를 최소화하는 방향으로 데이터 분할. 불순도에는 지니 불순도와 엔트로피가 있다.
- 마지막 노드에 있는 타겟값들의 최빈값을 예측값으로 반환

회귀 문제에서의 결정 트리
- MSE를 최소화하는 방향으로 데이터 분할
- 마지막 노드에 있는 타겟값들의 평균을 예측값으로 반환

 

A. 트리 모델에서의 인코딩


회귀 모델에서는 순서가 없는 범주형 특성에 모두 OneHotEncoder를 적용했다. 하지만 트리 모델에서는 OrdinalEncoder를 주로 이용한다. 회귀 모델처럼 직접적 연산을 하는 것이 아니기 때문이다.

 


B. 모델 생성 및 학습

# 파이프라인을 활용하면 결측치 처리와 인코딩과 모델 생성을 함께 할 수 있다.

pipe_dt = make_pipeline(
    OrdinalEncoder(),
    SimpleImputer(),
    DecisionTreeClassifier(criterion="entropy"),
)
pipe_dt.fit(X_train, y_train)

 

 

C. 시각화


어떤 질문이 각 노드에 들어갔는지 볼 수 있다

 

import graphviz
from sklearn.tree import export_graphviz

# named_steps()으로 파이프라인 각 스텝에 접근
model_dt = pipe_dt.named_steps['decisiontreeclassifier']
enc = pipe_dt.named_steps['ordinalencoder']
encoded_columns = enc.transform(X_val).columns

dot_data = export_graphviz(model_dt,
                          max_depth=3,
                          eature_names=encoded_columns,
                          class_names=['no', 'yes'],
                          filled=True,
                          proportion=True)

display(graphviz.Source(dot_data))

 



D. 하이퍼파라미터 튜닝


결정 트리는 과적합이 일어나기 쉽다. 하이퍼파라미터를 조정해 이를 해소할 수 있다. 트리의 복잡도를 줄이기 위해 많이 사용되는 파라미터는 다음과 같다.

  • min_sample_split
  • min_samples_leaf
  • max_depth



2. Random Forest

Decision Tree는 유연하지만 과적합이 될 위험이 있다. 또 작은 데이터 변동으로도 다른 트리가 생성될 수 있기에 매우 불안정하다. 이를 해결할 수 있는 방법이 앙상블이다. 

앙상블이란 여러개의 모델을 만들어 예측 결과를 종합적으로 반환하는 기법이다. 즉 하나의 결정 나무로 예측을 하는 것이 아니라, 여러 그루의 나무를 심어 예측값을 받아 종합적으로 예측을 한다. 앙상블애는 배깅과 부스팅이 있다. (부스팅은 2-2에서 다룬다)

랜덤 포레스트는 배깅을 이용한다. 앞서 통계에서 배웠던 부트스트래핑이 여기서도 이용된다. 원본 데이터에서 복원 추출을 하여 샘플 데이터를 만들고 이를 이용해 모델을 생성하고 학습한다. 이 과정을 여러번 거쳐 무수히 많은 나무(모델)를 만드는 것이다.  

예측값을 합치는 방법은 분류에서는 최빈값, 회귀에서는 평균값으로 한다. 


A. 모델 생성 및 학습

 

# 분류 모델을 만들어보자
from sklearn.ensemble import RandomForestClassifier

pipe_rf = make_pipeline(
    OrdinalEncoder(),
    SimpleImputer(),
    RandomForestClassifier(random_state=42, oob_score=True, n_jobs=-1),
)

pipe_rf.fit(X_train, y_train)

 

B. 평가


앞서 배웠던 회귀와 분류 평가지표를 사용할 수 있다. 그리고 random forest에서만 사용할 수 있는 oob score도 있다. 이 oob score는 부트스트래핑에서 샘플로 추출되지 않아 학습에 이용된 적 없는 데이터들을 모아 모델을 테스트하는 것이다.

 

pipe_rf.named_steps["randomforestclassifier"].oob_score_



C. 하이퍼파라미터 튜닝


위에서 언급한 decision tree의 주요 하이퍼파라미터가 random forest에서도 중요하다. 또, random forest에만 존재하는 것들도 있다.

  • n_estimators : 나무(모델)의 수
  • max_features : 분할에 사용되는 최대 특성 갯수
  • oob_score : oob sample을 이용한 검증 스코어 반환 여부