1-16 Decision Tree Classifier 와 GraphViz, PyDotPlus 설치

in #kr7 years ago (edited)

Decision Tree 기법은 간단히 설명하자면 Yes 또는 No 로 답하라는 미국 변호사들이 즐겨쓰는 기법이라 할 수 있는데 이미 헐리우드에서 변호를 주제로 하는 영화장르로 자리 잡은 지 오래다. 톰크루즈가 젊은 군 법무관으로 등장하는 A Few Good Man에서는 군대 내부의 불미스러운 사건에서 고위 장성이었던 잭 니콜슨이 말단 장교 법무관들이 감히 물어보지도 못하는 내용에 관하여 열 받은 상태에서 불법성이 있음에도 불구하고 국익 차원에서 일을 처리해야 만 했다고 스스로를 옭아매는 격렬한 증언 과정을 보여준다. 하지만 대부분의 미국 변호 영화에서는 항상 답하기 곤란한 질문을 던져 놓고 증인으로 하여금 “Yes” 아니면 “No” 로 답하라는 압박을 가하면서 흥미롭게 스토리를 풀어 간다.

noname01.png

Decision Tree 라는 학습 방법 명칭에서처럼 데이터를 일련의 질문을 바탕으로 단계별 의사결정을 통해서 분석하게 된다.
Iris flowers 데이터를 이용하는 학습문제에서도 동일한 방법을 적용하여 테스트 데이터의 class 라벨 명을 알아 낼 수 있는 것이다. 예를 들자면 꽃받침 크기 특징(feature)에 관한 컷오프(cut-off) 값을 설정할 수 있으며 “과연 꽃받침 크기가 2.8cm 보다 큰가?”라고 물어 볼 수 있는 것이다.

Tree의 뿌리에서부터 결정을 위한 알고리듬을 사용하면서 정보 이득값(Information Gain)이 가장 커질 수 있도록 데이터를 가지치기 해 나가야 한다. 즉 뿌리로부터 올라와 가지치기를 함에 따라 마지막 잎사귀에 도달하기까지 중간의 child node에서 가지 치는 과정이 반복되어야 한다. 하지만 실제 이러한 가지치기가 깊이 일어날 경우 Overfitting 현상이 일어날 수 있으므로 최대 깊이를 적절하게 제한해야 할 필요가 있다.

따라서 scikit-learn 라이브러리를 이용함에 있어서 Tree 의 최대 깊이를 4로 제한하도록 한다. 아울러 가시화를 위해서 특징 데이터의 Scaling(축척) 작업이 필요할 수도 있는데 이는 Decision Tree 알고리듬의 요구 조건은 아니지만 기법 이해에 크게 도움이 됨을 이해하자.
scikit-learn 학습 결과로서 .DOT 파일을 생성하는데 GraphViz 프로그램을 이용하여 가시화 해 볼 수 있는 이점이 있다. 참고로 GraphViz는 각종 Computational Graph 작도에 중요하게 사용되는 오픈 소스 코드이다.

윈도우즈10 시스템 GraphViz 설치
아나콘다를 설치해서 사용하는 윈도우즈10 시스템에서 GraphViz 설치에 대단히 중요한 점은 GraphViz는 아나콘다 내부의 가상환경 TensorFlow 가 아닌 시스템에 설치해야 한다는 점이다. 반면에 동시에 설치해야 하는 Pydotplus는 가상환경 TensorFlow에 설치하도록 한다. 이점에 유의해야 하며 그렇치 않을 경우 엄청난 시간 낭비가 뒤따르게 된다.

Graph.org 사이트에서 Download로 들어가도록 하자.

noname02.png

윈도우즈10에 설치하기 위한 Stable 2.38 Windows install packages를 찾아서 설치하도록 한다.

noname03.png

하이퍼링크 Stable 2.38 Windows install packages를 클릭하면 아래의 화면이 나타난다. 하이퍼링크 graphviz-2.38.msi를 클릭하도록 한다.

noname04.png

화면 하단에서 실행 버튼을 클릭하여 직접 설치하도록 한다.

noname05.png

설치가 완료되면 폴더 주소를 확인하도록 한다.
C:, Program Files(x86), Graphviz2.38,bin 안에 GraphViz 파일이 확인되면 마우스 오른쪽 버튼으로 url 폴더 주소를 복사한다.
noname06.png

윈도우즈10 시스템의 제어판을 열어서 시스템으로 들어간다.

noname07.png

제어판 왼쪽 밑의 고급시스템 설정을 클릭해 들어가면 시스템 속성 창이 뜨는데 환경변수버튼을 클릭한다.

noname08.png

환경변수 창에서 Path 부분을 선택 클릭 후 편집 버튼을 클릭한다.

noname09.png

환경변수 편집에서 흰색 박스에 앞서 주소복사했던 내용을 붙이기 작업 완료되면 확인 버튼을 눌러 제어판을 빠져 나간다. 설정된 PATH를 적용하려면 반드시 컴퓨터를 재 시작해야 한다.

noname10.png

PyDotPlus 설치
pydotplus 라이브러리는 DecisionTreeClassifier 파이선 코드에서 제공하는 DOT 파일과 GraphViz를 인터페이스하는 역할을 한다. 따라서 pydotplus는 아나콘다 창을 열어서 command line 명령 activate tensorflow를 실행 시킨 후 가상환경 tensorflow 프롬프트가 뜨면 별도의 파일 다운로드 필요 없이command line 명령 pip install pydotplus 을 직접 실행하여 라이브러리를 설치하자.

noname11.png

다음과 같이 셸에서 확인 작업을 하도록 하자.
GraphViz와 PyDotPlus 설치 여부는 아나콘다 스파이더 셸(Shell)을 열어서 다음과 같이 명령을 실행하여 아무런 에러가 뜨지 않으면 성공적으로 설치가 된 것이다.

noname12.png
noname13.png

첨부된 코드 #ch03_decision_tree_01.py를 실행하면 다음과 같이 전형적인 박스 형태로 분류된 Decision Tree classification 결과가 얻어진다.

noname14.png

한편 DOT 파일을 처리한 tree.png 파일은 실행되는 파이선 코드가 저장되어 있는 폴더에서 찾아야 한다.

아래의 Tree.png 다이아그램을 보고 DecisionTreeClassifier이해에 참고하도록 하자. 아래에 출력된 그래프 내용을 살펴보니 DecisionTreeClassifier 실행에 내부적으로 gini 계수 및 Information Gain 과 같은 개념이 필요해 보인다. 이 문제에 관해서는 별도로 내용을 준비할 예정이다.

noname16.png

#ch03_decision_tree_01.py

from sklearn import version as sklearn_version
from sklearn import datasets
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier

#Loading the Iris dataset from scikit-learn. Here, the third column represents the petal length, and the fourth column the petal width of the flower samples. The classes are already converted to integer labels where 0=Iris-Setosa, 1=Iris-Versicolor, 2=Iris-Virginica.

iris = datasets.load_iris()
X = iris.data[:, [2, 3]]
y = iris.target

print('Class labels:', np.unique(y))

#Splitting data into 70% training and 30% test data:

X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=1, stratify=y)

print('Labels counts in y:', np.bincount(y))
print('Labels counts in y_train:', np.bincount(y_train))
print('Labels counts in y_test:', np.bincount(y_test))

#Standardizing the features:
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):

# setup marker generator and color map
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])

# plot the decision surface
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                       np.arange(x2_min, x2_max, resolution))
Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())

for idx, cl in enumerate(np.unique(y)):
    plt.scatter(x=X[y == cl, 0], 
                y=X[y == cl, 1],
                alpha=0.8, 
                c=colors[idx],
                marker=markers[idx], 
                label=cl, 
                edgecolor='black')

# highlight test samples
if test_idx:
    # plot all samples
    X_test, y_test = X[test_idx, :], y[test_idx]

    plt.scatter(X_test[:, 0],
                X_test[:, 1],
                c='',
                edgecolor='black',
                alpha=1.0,
                linewidth=1,
                marker='o',
                s=100, 
                label='test set')

#Decision tree learning

tree = DecisionTreeClassifier(criterion='gini',
max_depth=4,
random_state=1)
tree.fit(X_train, y_train)

X_combined = np.vstack((X_train, X_test))
y_combined = np.hstack((y_train, y_test))
plot_decision_regions(X_combined, y_combined,
classifier=tree, test_idx=range(105, 150))

plt.xlabel('petal length [cm]')
plt.ylabel('petal width [cm]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

from pydotplus import graph_from_dot_data
from sklearn.tree import export_graphviz
dot_data = export_graphviz(
tree, filled=True, rounded=True, class_names=['Setosa', 'Versicolor', 'Virginica'],
feature_names=['petal_length', 'petal_width'], out_file=None)

graph = graph_from_dot_data(dot_data)
graph.write_png('tree.png')

마나마인로고.png

Sort:  

Congratulations @codingart! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You published more than 550 posts. Your next target is to reach 600 posts.

You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.04
TRX 0.33
JST 0.098
BTC 64607.46
ETH 1878.41
USDT 1.00
SBD 0.38