#!/usr/bin/env python3


Decision Tree


Decision Tree결정트리는 True/False 질문을 이어나가면서 학습합니다.


다음 코드는 decision tree의 algorithm을 보여줍니다.

from mglearn.plots import plot_animal_tree

import matplotlib.pyplot as plt


plot_animal_tree()

plt.show()

몇 가지 동물들을 구분하기 위한 결정 트리

여기에서 tree의 node는 질문이나 정답을 담은 네모 상자를 말하며

root node는 최상위 node이고

leaf node는 마지막 node입니다.


decision tree를 학습한다는 것은 정답에 가장 빨리 도달하는 True/False 질문 목록을 학습하는 것입니다.

머신러닝에서 이런 질문들을 'test'라 합니다.


만약 tree를 만들 때 모든 leaf node가 pure node가 될 때 까지 진행하면 model의 complexity는 매우 높아지고 overfitting됩니다. 즉 train set의 모든 데이터포인트가 leaf node에 있다는 뜻입니다.


overfittng을 막는 전략은 크게 2가지가 있습니다.

1. tree 생성을 사전에 중단합니다 : pre-pruning

2. 데이터 포인트가 적은 node를 삭제하거나 병합합니다 : post-pruning



이제는 실제 데이터셋(wine dataset)으로 decision tree 분석을 해보겠습니다.

from sklearn.datasets import load_wine

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier


wine = load_wine()


x_train, x_test, y_train, y_test = train_test_split(wine.data, wine.target,

                                                    stratify=wine.target, random_state=0)


tree = DecisionTreeClassifier(random_state=0)

tree.fit(x_train, y_train)


score_tr = tree.score(x_train, y_train)

score_te = tree.score(x_test, y_test)


print('{:.3f}'.format(score_tr))

# 1.000


print('{:.3f}'.format(score_te))

# 0.889

모든 leaf noe가 pure node이므로 train set의 정확도는 100%입니다.

tree는 train set의 모든 포인트들을 완벽하게 구분할 만큼 깊게 만들어집니다. 따라서 overfitting의 가능성이 매우 높아집니다.



이런 overfitting을 막기위해 깊이를 제한하는 방법을 사용할 수 있습니다.

pre-pruning의 방법 중 하나는 깊이의 최대를 설정하는 것입니다.

tree = DecisionTreeClassifier(max_depth=2, random_state=0)

tree.fit(x_train, y_train)


score_tr = tree.score(x_train, y_train)

score_te = tree.score(x_test, y_test)


print('{:.3f}'.format(score_tr))

# 0.910


print('{:.3f}'.format(score_te))

# 756

train_set의 score가 낮아진 것으로 보아 overfitting은 감소한 것처럼 보이지만, test set의 score또한 낮아졌으므로 이 데이터셋에 tree model은 적합하지 않음을 알 수 있습니다.



tree module의 export_graphviz함수를 이용해 tree를 시각화할 수 있습니다.

graphviz를 설치한 후 사용가능합니다

import graphviz

from sklearn.tree import export_graphviz


export_graphviz(tree, out_file='tree.dot',

                class_names=wine.target_names,

                feature_names=wine.feature_names,

                impurity=False# gini 미출력

                filled=True) # filled: node의 색깔을 다르게


with open('tree.dot') as file_reader:

    dot_graph = file_reader.read()


dot = graphviz.Source(dot_graph) # dot_graph의 source 저장

dot.render(filename='tree.png'# png로 저장

tree.png

wine 데이터셋으로 만든 Decision Tree

가장 중요한 특성이 proline아미노산임을 알 수 있습니다.



tree는 어떻게 작동하는지 요약하는 속성들을 사용할 수 있습니다.

가장 널리 사용되는 속성은 tree를 만드는 결정에 각 특성이 얼마나 중요한지는 평가하는 feature importance특성 중요도가 있습니다.

이 값은 0과 1사이의 숫자로 0은 전혀 사용되지 않았다는 뜻이고 1은 완벽하게 예측했다는 뜻입니다.

feature_imp = tree.feature_importances_

print('{}'.format(feature_imp))

# [0.         0.         0.         0.02885475 0.         0.

#  0.         0.         0.         0.43979596 0.         0.

#  0.53134929]



더 자세히 알아보기 위해 feature_importance를 시각화를 하겠습니다.

import numpy as np

n_feature = wine.data.shape[1]

idx = np.arange(n_feature)


plt.barh(idx, feature_imp, align='center')

plt.yticks(idx, wine.feature_names)

plt.xlabel('feature importance', size=15)

plt.ylabel('feature', size=15)

plt.show()

feature importance와 feature

root node에서 사용한 특성 'proline'이 가장 중요한 특성으로 나타납니다.


feature_importances_ 값이 낮다고 해서 이 특성이 유용하지 않다는 뜻은 아닙니다.

단지 이 tree가 특성을 선택하지 않았을 뿐이며, 다른 특성이 동일한 정보를 가지고 있어서 일 수도 있습니다.


feature importance 값은 'proline'가 중요하다가 알려주지만 이 값이 양성인지 음성인지는 알 수 없습니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Gradient Boosting Model  (0) 2018.03.15
Random Forest  (0) 2018.03.15
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12

+ Recent posts