Data Science/Machine Learning

Classification 1. 결정 트리(Decision Tree)

HJChung 2020. 10. 8. 16:36

권철민 강사님의 '파이썬 머신러닝 완벽 가이드'을 학습하고 정리한 것입니다. 배우는 중이라 잘못된  내용이 있을 수 있으며 계속해서 보완해 나갈 것입니다. :)) 

분류(Classification)란

학습 데이터로 주어진 데이터의 feature와 label값을 머신러닝 알고리즘으로 학습해 모델을 생성하고, 학습된 모델에 새로운 feature 값(독립변수)이 주어졌을 때, 그 값과 가장 연관도니 label(종속변수; class)값을 예측하는 것이다. 

<데이터 사이언스 스쿨>의 설명에 따르면, ' 어떤 표본에 대한 데이터가 주어졌을 때,  그 표본이 어떤 카테고리 혹은 클래스에 속하는지를 알아내는 문제'로 볼 수 있다. 

대표적인 분류 알고리즘

  • 나이브 베이즈(Naive Bayes Classification)
  • 로지스틱 회귀(Logistic Regression) - sigmoid 함수를 사용하여 분류 알고리즘으로 사용할 수 있는 로짓스틱 회귀
  • 결정 트리(Decision Tree)
  • 서포트 백터 머신(Support Vector Machine)
  • 최소 근접 알고리즘(Nearest Neighbor search)
  • 신경망 (Neural Network)
  • 앙상블 (Ensemble)

 

먼저 결정 트리부터 자세히 알아본다. 

결정 트리

결정 트리는 '규칙'을 학습을 통해 찾고, 트리 구조의 분류 규칙을 만든다. (is-else 기반 규칙)

그리고 이렇게 만들어진 분류 규칙으로 분류값을 결정한다. 따라서 주어진 데이터를 어떤 기준을 바탕으로 규칙을 만들어 가장 적합한 분류를 할 수 있을 것인가가 알고리즘의 성능으로 이어질테고, 최대한 균일한 데이터 세트를 구성할 수 있도록 분류하는 것이 그 중 하나이다. 

1. 정보 균일도

결정 트리에서 정보 균일도 측정 방법에는 정보 이득 지수와 지니 계수가 있다. 

  • 정보 이득 지수: 엔트로피는 정보가 가지는 기대값으로 불확실성을 나타내는 지표이다. 그래서 서로 다른 값이 많이 섞여 있으면 엔트로피가 높고, 같은 값이 섞여 있으면 엔트로피가 낮다. 정보 이득 지수는 1-엔트로피 지수로, 1-서로 값은 값이 섞여있는 경우(균일)의 엔트로피(낮은값) = 높은 정보 이득 지수  이므로 정보 이득 지수가 높은 속성을 기준으로 분할한다. 
  • 지니 계수: 지니 계수는 0일 때 가장 평등(균일)하고 1로 갈수록 불평등(균일하지 않음) 이다. 그래서 지니 계수가 낮은 속성을 기준으로 분할한다. 

그래서 정보 이득이 높거나, 지니 계수가 낮은 조건을 찾아서 자식 트리 노드에 걸쳐 반복적으로 분할한 뒤, 데이터가 모두 특정 분류에 속하게 되면 분할을 멈추고 분류를 결정한다. 

2. 결정 트리의 특징

결정 트리의 장점)

- 정보의 균일도를 기반으로 하고있어서 알고리즘이  쉽고 직관적이다. 

- 시각화로 표현 할 수 있다. 

- 정보의 균일도만 신경 쓰면 되므로 feature 스케일링이나 normalization과 같은 데이터 전처리 작업이 필요 없다. 

결정 트리의 단점)

- 모든 데이터 상황을 만족하도록 트리의 조건을 계속 추가하다보면 과적합이 발생한다. 그러므로 모든 데이터 상황을 만족할 필요는 없게 사전에 트리 크기를 제한하는 것이 필요하기도 하다.

3. 결정 트리의 활용

결정 트리는 분류(Classification)과 회귀(Regression) 모델로 모두 사용가능하다. 

출처: ratsgo.github.io/machine%20learning/2017/03/26/tree/

💡의사결정나무는 분류(classification) 회귀(regression) 모두 가능합니다. 범주나 연속형 수치 모두 예측할 수 있다는 말입니다. 의사결정나무의 범주예측, 즉 분류 과정은 이렇습니다. 새로운 데이터가 특정 terminal node에 속한다는 정보를 확인한 뒤 해당 terminal node에서 가장 빈도가 높은 범주에 새로운 데이터를 분류하게 됩니다. 운동경기 예시를 기준으로 말씀드리면 날씨는 맑은데 습도가 70을 넘는 날은 경기가 열리지 않을 거라고 예측합니다.

회귀의 경우 해당 terminal node의 종속변수(y)의 평균을 예측값으로 반환하게 되는데요, 이 때 예측값의 종류는 terminal node 개수와 일치합니다. 만약 terminal node 수가 3개뿐이라면 새로운 데이터가 100개, 아니 1000개가 주어진다고 해도 의사결정나무는 딱 3종류의 답만을 출력하게 될 겁니다. 💡

4. sklearn과 결정 트리 

앞서 '결정 트리는 분류(Classification)과 회귀(Regression) 모델로 모두 사용가능하다.' 라고 정리했다. sklearn은 분류를 위한 결정 트리 알고리즘 클래스 'DecisionTreeClassifier'와 회귀를 위한 'DecisionTreeRegressor' 을 제공한다. 

'DecisionTreeClassifier'

class sklearn.tree.DecisionTreeClassifier(*, criterion='gini', splitter='best', max_depth=None, 
	min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0,
    max_features=None, random_state=None, max_leaf_nodes=None,min_impurity_decrease=0.0,
    min_impurity_split=None, class_weight=None, presort='deprecated', ccp_alpha=0.0)

'DecisionTreeRegressor'

class sklearn.tree.DecisionTreeRegressor(*, criterion='mse', splitter='best', max_depth=None, 
	min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0,
    max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0,
    min_impurity_split=None, presort='deprecated', ccp_alpha=0.0)

주요 Parameter)

앞의 결정 트리의 단점 에서 과적합을 막기위해서 트리 크기를 제한하는 것이 필요하기도 하다고 했다. 이때 사용하는 파라미터가 이것들과 같다.

5. 결정 트리 모델의 시각화

1) Graphviz를 이용한 결정 트리 모델의 시각화

Graphviz는 그래프 기반의 dot 파일로 기술된 다양한 이미지를 시각화 할 수 있는 패키지이다. 

 

 

In [1]:
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')

# DecisionTree Classifier 생성
dt_clf = DecisionTreeClassifier(random_state=156)

# 붓꽃 데이터를 로딩하고, 학습과 테스트 데이터 셋으로 분리
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)

# DecisionTreeClassifer 학습. 그러면 dt_clf가 학습완료된 classifier가 된다. 
dt_clf.fit(X_train , y_train)
Out[1]:
DecisionTreeClassifier(random_state=156)
In [2]:
from sklearn.tree import export_graphviz

# export_graphviz는 학습완료된 dt_clf를 out_file로 지정된 파일로 만들어줌 
# 이때 target_name과 feature_name을 넣어줘야 그래프가 완성된다. 
export_graphviz(dt_clf, out_file="tree.dot", class_names=iris_data.target_names , \
feature_names = iris_data.feature_names, impurity=True, filled=True)
In [3]:
import graphviz

# 위에서 생성된 tree.dot 파일을 Graphviz 읽어서 Jupyter Notebook상에서 시각화 
with open("tree.dot") as f:
    dot_graph = f.read()
graphviz.Source(dot_graph)
Out[3]:
petal length (cm) <= 2.45 gini = 0.667 samples = 120 value = [41, 40, 39] class = setosa gini = 0.0 samples = 41 value = [41, 0, 0] class = setosa True petal width (cm) <= 1.55 gini = 0.5 samples = 79 value = [0, 40, 39] class = versicolor False petal length (cm) <= 5.25 gini = 0.051 samples = 38 value = [0, 37, 1] class = versicolor petal width (cm) <= 1.75 gini = 0.136 samples = 41 value = [0, 3, 38] class = virginica gini = 0.0 samples = 37 value = [0, 37, 0] class = versicolor gini = 0.0 samples = 1 value = [0, 0, 1] class = virginica sepal length (cm) <= 5.45 gini = 0.5 samples = 4 value = [0, 2, 2] class = versicolor petal length (cm) <= 4.85 gini = 0.053 samples = 37 value = [0, 1, 36] class = virginica gini = 0.0 samples = 1 value = [0, 0, 1] class = virginica petal length (cm) <= 5.45 gini = 0.444 samples = 3 value = [0, 2, 1] class = versicolor gini = 0.0 samples = 2 value = [0, 2, 0] class = versicolor gini = 0.0 samples = 1 value = [0, 0, 1] class = virginica sepal length (cm) <= 5.95 gini = 0.444 samples = 3 value = [0, 1, 2] class = virginica gini = 0.0 samples = 34 value = [0, 0, 34] class = virginica gini = 0.0 samples = 1 value = [0, 1, 0] class = versicolor gini = 0.0 samples = 2 value = [0, 0, 2] class = virginica

 

2) sklearn의 feature_importance_ 속성으로 중요한 feature 시각화

sklearn의 DecisionClassifier객체는 feature_importances_속성을 통해 중요한 feature 들을 ndarray형태로 값을 반환한다. 예를 들어, 

[0.01667, 0.02500, 0.03200, 0.926318] 이라면 첫 번째 feature 중요도가 0.01667, 두 번째 feature 중요도가 0.02500 이다. 즉, 값이 높을 수록 중요한 feature이다. 

 

 

In [1]:
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')

# DecisionTree Classifier 생성
dt_clf = DecisionTreeClassifier(random_state=156)

# 붓꽃 데이터를 로딩하고, 학습과 테스트 데이터 셋으로 분리
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)

# DecisionTreeClassifer 학습. 그러면 dt_clf가 학습완료된 classifier가 된다. 
dt_clf.fit(X_train , y_train)
Out[1]:
DecisionTreeClassifier(random_state=156)
In [2]:
import seaborn as sns
import numpy as np
%matplotlib inline

# feature importance 추출 
print("Feature importances:\n{0}".format(np.round(dt_clf.feature_importances_, 3)))

# feature별 importance 매핑
for name, value in zip(iris_data.feature_names , dt_clf.feature_importances_):
    print('{0} : {1:.3f}'.format(name, value))

# feature importance를 column 별로 시각화 하기 
sns.barplot(x=dt_clf.feature_importances_ , y=iris_data.feature_names)
 
Feature importances:
[0.025 0.    0.555 0.42 ]
sepal length (cm) : 0.025
sepal width (cm) : 0.000
petal length (cm) : 0.555
petal width (cm) : 0.420
Out[2]:
<AxesSubplot:>
 

 

3) overfitting 여부 시각화 

분류를 위한 feature2개, class는 3개인 임의의 샘플 데이터를 생성하여 parameter를 조절하면서 overfitting여부를 시각화 할 수 있는 방법 코드

 

 

 

 

 

 

6. 결정 트리와 앙상블

 앙상블은 기반 알고리즘으로 결정 트리 모델을 사용한다. 

결정 트리를 간단히 보면, 

결정 트리는 매우 쉽고 유연하게 적용될 수 있는 알고리즘이다. 또한 데이터의 스케일링이나 정규화 등의 사전 가공의 영향이 매우 적다. 하지만 예측 성능을 향상시키기 위해 복잡한 규칙 구조를 가져야하며, 이로 인한 과적합이 발생해 반대로 예측 성능이 저하될 수도 있다.

그러나 앙상블에서는 이러한 결정 트리의 단점이 순화되고, 강점이 강조된다. 

앙상블은 매우 많은 여러개의 약한 학습기(weak learner)(예측 성능이 상대적으로 떨어지는 학습 알고리즘)을 결합하여 확률적 보완과 오류가 발생한 부분에 대한 가중치를 계속 업데이트하면서 예측 성능을 향상시키는데, 결정 트리가 좋은 약한 학습기가 되기 때문이다. 

 

 

지금까지 파이썬 머신러닝 완벽 가이드 수업을 바탕으로 

분류 알고리즘 중 결정 트리에 대해서 알아보았다. 

 

다음 포스트에서는 앙상블 학습을 통한 분류에 대해서 정리해 볼 것이다. 

 

Reference

파이썬 머신러닝 완벽 가이드 - 권철민 저

datascienceschool.net/03%20machine%20learning/09.03%20분류모형.html?highlight=분류