의사결정나무 실습

·2021년 12월 9일
0

NIPA AI 교육

목록 보기
14/31

1. sklearn을 사용한 의사결정나무 - 데이터 전 처리

이번 실습에서는 분류 문제 해결을 위해 Iris 데이터를 사용합니다. Iris 데이터는 아래와 같이 꽃받침 길이, 꽃받침 넓이, 꽃잎 길이, 꽃잎 넓이 네 가지 변수와 세 종류의 붓꽃 클래스로 구성되어 있습니다.

꽃받침 길이, 꽃받침 넓이, 꽃잎 길이, 꽃잎 넓이 네 가지 변수가 주어졌을 때, 어떠한 붓꽃 종류인지 예측하는 분류 모델을 구현해보도록 하겠습니다.

우선 데이터를 전 처리 하기 위해서 4개의 변수를 갖는 feature 데이터와 클래스 변수를 label 데이터로 분리하고 학습용, 평가용 데이터로 나눠봅시다.

지시사항
load_iris로 읽어 온 데이터 X에서 Y 를 바탕으로 train_test_split를 사용하여 학습용:평가용=8:2학습용 : 평가용 = 8:2학습용:평가용=8:2 비율로 분리합니다. (random_state=42는 고정합니다.)

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

from elice_utils import EliceUtils
elice_utils = EliceUtils()


# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_iris(return_X_y = True)

# DataFrame으로 변환
df = pd.DataFrame(X, columns=['꽃받침 길이','꽃받침 넓이', '꽃잎 길이', '꽃잎 넓이'])
df['클래스'] = Y

X = df.drop(columns=['클래스'])
Y = df['클래스']

"""
1. 학습용 평가용 데이터로 분리합니다
"""
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)

# 원본 데이터 출력
print('원본 데이터 : \n',df.head(),'\n')

# 전 처리한 데이터 5개만 출력합니다
print('train_X : ')
print(train_X[:5],'\n')
print('train_Y : ')
print(train_Y[:5],'\n')

print('test_X : ')
print(test_X[:5],'\n')
print('test_Y : ')
print(test_Y[:5])

2. sklearn을 사용한 의사결정나무 - 학습하기

앞에서 전 처리한 데이터를 바탕으로 의사결정나무 모델을 학습하겠습니다.

각 노드에서 불순도를 최소로 하는 의사결정나무 모델을 구현하기 위해서는 sklearn의 DecisionTreeClassifier을 사용합니다. 이 모델을 학습하고 모델의 구조를 살펴봅시다.

DecisionTreeClassifier (sklearn)
DecisionTreeClassifier을 사용하기 위해서는 우선 해당 모델 객체를 불러와 초기화해야 합니다. 아래 코드는 DTmodel에 모델 객체를 초기화 하는 것을 보여줍니다.
DTmodel = DecisionTreeClassifier()

모델 초기화를 수행했다면 전 처리된 데이터를 사용하여 학습을 수행할 수 있습니다. 아래 코드와 같이 fit 함수에 학습에 필요한 데이터를 입력하여 학습을 수행합니다.
DTmodel.fit(train_X, train_Y)

지시사항
sklearn의 DecisionTreeClassifier() 모델을 DTmodel에 초기화 합니다.

fit을 사용하여 train_X, train_Y 데이터를 학습합니다.

Tips!
DTmodel = DecisionTreeClassifier(max_depth=2)

위 코드처럼 초기화를 수행할 때 max_depth를 설정하여 의사결정나무의 최대 깊이를 조절할 수 있습니다. 2 이외의 다른 값을 넣어서 확인해보세요.

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import tree

from elice_utils import EliceUtils
elice_utils = EliceUtils()


# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_iris(return_X_y = True)

# DataFrame으로 변환
df = pd.DataFrame(X, columns=['꽃받침 길이','꽃받침 넓이', '꽃잎 길이', '꽃잎 넓이'])
df['클래스'] = Y

X = df.drop(columns=['클래스'])
Y = df['클래스']
    
# 학습용 평가용 데이터로 분리합니다
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)

# DTmodel에 의사결정나무 모델을 초기화 하고 학습합니다
DTmodel = DecisionTreeClassifier()
DTmodel.fit(train_X, train_Y)


# 학습한 결과를 출력합니다
plt.rc('font', family='NanumBarunGothic')
fig = plt.figure(figsize=(25,20))
_ = tree.plot_tree(DTmodel, 
                   feature_names=['꽃받침 길이','꽃받침 넓이', '꽃잎 길이', '꽃잎 넓이'],  
                   class_names=['setosa', 'versicolor', 'virginica'],
                   filled=True)

fig.savefig("decision_tree.png")
elice_utils.send_image("decision_tree.png")

3. sklearn을 사용한 의사결정나무 - 예측하기

[실습3]에서 학습한 모델을 바탕으로 새로운 데이터에 대해서 예측해보겠습니다.

test_X 데이터에 따른 예측값을 구해봅시다

DecisionTreeClassifier (sklearn)
DecisionTreeClassifier을 사용하여 예측을 해야 한다면 아래와 같이 predict 함수를 사용합니다.

pred_X = DTmodel.predict(test_X)

지시사항
DTmodel을 학습하고 test_X의 예측값을 구하여 pred_X에 저장합니다.

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import tree

from elice_utils import EliceUtils
elice_utils = EliceUtils()


# sklearn에 저장된 데이터를 불러 옵니다.
X, Y = load_iris(return_X_y = True)

# DataFrame으로 변환
df = pd.DataFrame(X, columns=['꽃받침 길이','꽃받침 넓이', '꽃잎 길이', '꽃잎 넓이'])
df['클래스'] = Y

X = df.drop(columns=['클래스'])
Y = df['클래스']
    
# 학습용 평가용 데이터로 분리합니다
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2, random_state = 42)

# DTmodel에 의사결정나무 모델을 초기화 하고 학습합니다
DTmodel = DecisionTreeClassifier()
DTmodel.fit(train_X, train_Y)


# test_X에 대해서 예측합니다.
pred_X = DTmodel.predict(test_X)
print('test_X에 대한 예측값 : \n{}'.format(pred_X))

## 추가로 test_Y 를 출력해서 예측이 잘 됐는지 확인해보았다.
print(test_Y)

## 보니까 잘 예측이 된 거 같아서, max_depth를 줄여서 모델을 초기화하고 학습시켜 예측해보았다.
# DTmodel = DecisionTreeClassifier() 를
# DTmodel = DecisionTreeClassifier(max_depth=2) 로 변경

## 결과: max_depth의 제한이 없이 depth 6개로 된 기존 모델은 전부 다 맞게 예측됐고, max_depth를 2로 제한한 모델은 한 개 틀리고 다 맞았다.

아무 생각없이 실습 진행하다, 도대체 붓꽃에 대한 iris데이터를 어디서 불러온 거지? 하고 생각했는데 검색해보니 고전적인 데이터로 sklearn에 기본적으로 포함돼있는 거였다.
참조: https://computer-nerd.tistory.com/52

profile
백엔드 개발자. 공동의 목표를 함께 이해한 상태에서 솔직하게 소통하며 일하는 게 가장 즐겁고 효율적이라고 믿는 사람.

0개의 댓글