본문 바로가기
[AI] - Machine Learning

# 8. 의사 결정 나무 (Decision Tree)

by Bebsae 2021. 10. 24.

의사 결정 나무에 대한 내용을 다루기 이전에 지금까지 정리했던 내용을 큰 맥락으로 한번 짚고 넘어갈까 한다.

 

1. 전처리

1.1 encoding

from sklearn.preprocessing import LabelEncoder

from skelarn.preprocessing import OneHotEncoder

 

1.2 feature scaling

from sklearn.preprocessing import StandardScaler

from sklearn.preprocessing improt MinMaxScaler

 

1.3 학습 데이터 분리 & 교차검증

from sklearn.model_selection import train_test_split

from sklearn.model_selection import KFold

from sklearn.model_selection import StratifiedKFold

 

2. 알고리즘

 

3. 후처리

3.1 평가지표

from sklearn.metrics import confusion_matrix

from skelarn.metrics import accuracy_score

from skelarn.metrics import precision_score

from skelarn.metrics import recall_score

from skelarn.metrics import f1_score

from skelarn.metrics import roc_curve

from sklearn.metrics import roc_auc_score

 

앞으로 나올 내용들도 "전처리 - 알고리즘 - 후처리"의 패러다임으로 진행되며, 알고리즘에 대한 내용들을 다룰 예정이다.

 

.

.

.

 

Decision Tree는 규칙을 기반으로 트리 형태로 if ~ else ~ 분기를 하는 알고리즘이다. 쉽고 직관적이며 설명가능(White box)한 것이 특징이다. 다만, 트리의 깊이가 깊어질수록 오버피팅이 나타날 수 있다.

 

트리의 노드는 크게 세 가지 종류로 루트노드(최상위노드), 규칙노드(중간노드 - 규칙에 의해 분기하는 노드), 리프노드(최하위노드, 말단노드)가 있다.

 

Decision Tree가 분기를 멈추는 시점은 정보가 균일해질 때까지 분기를 하는데, 정보의 균일도를 측정하는 대표정인 방법은 정보 이득(Information Gain)지니계수가 있다. (정보 이득 = 1 - 엔트로피지수)

 

아래의 Decision Tree를 보면서 노드의 의미를 파악해보자.

 

 

리프노드를 제외한 나머지 노드들은 (각 행별로) 5개의 값을 가지고 있다. 

1. 분기 조건

2. 지니계수

3. 해당 노드에 존재하는 샘플의 수

4. 각 클래스별 샘플의 수

5. 해당 노드에 가장 많은 샘플의 수를 지닌 클래스

 

Decision Tree의 크기가 커지면 물론 학습 데이터에 대한 예측은 섬세해질 수 있지만, 일반화가 되지 못하여 오버피팅 문제를 야기할 수 있다. 이러한 문제를 해결하기 위해 Decision Tree에는 다양한 파라미터들이 존재한다. 이에 대해서 살펴보자.

 

min_samples_split
(Default : 2)
* 노드를 분할하기 위한 최소의 샘플 수
min_samples_leaf * 리프노드가 되기 위한 최소의 샘플 수
* 불균형한 데이터셋의 경우 특정 클래스의 샘플 수가 매우 적을 수 있으므로 작게 설정할 필요가 있다.
max_features
(Default : None - 피처 전부 사용)
* 분할을 위해 고려할 피처의 수
* int로 지정할 경우, 사용할 피처의 수
* float으로 지정할 경우, 사용할 피처의 비율
max_depth * 트리의 최대 깊이
max_leaf_nodes * 리프노드의 최대 갯수

 

Decision Tree에는 분류를 위한 클래스(DecisionTreeClassifier)와 회귀를 위한 클래스(DecisionTreeRegressor)가 있지만, 여기서는 DecisionTreeClassifier만 다루겠다. 코드를 통해 DecisionTreeClassifier를 생성하여 시각화하는 부분까지 보겠다.

 

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

# 데이터셋 분리
iris_data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, test_size=0.2, random_state=11)

# 의사결정 나무 분류기 생성
dt_clf = DecisionTreeClassifier(random_state=156)

# 학습
dt_clf.fit(X_train, y_train)
from sklearn.tree import export_graphviz

# scikit-learn의 graphviz를 위한 메소드
# tree.dot 파일로 시각화 결과 저장
export_graphviz(dt_clf, out_file="tree.dot", 
                class_names=iris_data.target_names, 
                feature_names=iris_data.feature_names,
                impurity=True, filled=True)
import graphviz

# 저장한 tree.dot 파일을 불러와서 표시
with open("tree.dot") as f:
    dot_graph = f.read()
graphviz.Source(dot_graph)

 

위와 같이 실행을 하면 DecisionTreeClassifier의 분류 결과를 볼 수 있을 것이다. 하지만, 현재 분류기는 파라미터를 모두 default로 사용한 상태이다. 파라미터를 달리하여 학습을 진행할 때, 하이퍼 파라미터를 손수 입력해주며 실행하는 것보다 더 좋은 방법을 이전에 언급했다. 그것은 바로 GridSearchCV이다. 여기서 CV는 Cross Validation을 의미한다.

 

마지막으로 Decision Tree의 큰 장점은 중요한 피처(feature_importances_)를 빠르게 확인할 수 있다는 점이다.

 

import seaborn as sns

# feature importance를 column 별로 시각화 하기 
sns.barplot(x=dt_clf.feature_importances_ , y=iris_data.feature_names)

댓글