본문 바로가기
Machine Learning

Decision Tree

by Nowkeeh Ahc

 비즈니스 분야의 분류 예측 머신러닝 모형으로 가장 많은 각광을 받아왔던 의사결정나무 모형에 대해 포스팅 하려고 한다.  의사결정나무는 분류 예측뿐만 아니라 수치 예측에도 사용할 수 있지만, 주로 분류 예측에 더 많이 사용되어 왔다. 의사결정나무는 명확하고, 이해하기 쉬운 알고리즘을 기반으로 작동할 뿐만 아니라 모형 자체를 시각화할 수도 있기 때문에 인기가 매우 많았던 모델 중 하나이다.

 

의사결정나무 (Decision Tree)란 데이터에 내재되어 있는 패턴을 나무 형태로 도표화하여 분류 또는 수치를 예측하는 모형이다. 의사결정나무는 전체 데이터를 특정 분류 기준에 따라 점차적으로 데이터를 두 개 혹은 그 이상의 부분집합으로 분할하여 부분집합에 있는 데이터가 어떠한 범주 혹은 수치를 갖는지 판단하여 예측을 수행한다. 따라서 의사결정나무 모형의 최대 목표는 최적의 분할변수와 분할점을 선택하는 것이며, 분류의 문제에서는 비슷한 범주를 갖고 있는 관측치끼리, 예측의 문제에서는 비슷한 수치를 갖고 있는 관측치끼리 모아 나무의 마디를 형성하고 뻗어나간다.

 

아래 그림은 의사결정나무 모형의 구성요소를 시각적으로 표현한 것이다.

[그림 1] 의사결정나무 모형의 구성요소

 

아래 표는 [그림 1]에 명시된 의사결정나무 모형의 구성요소를 설명한 것이다. 

[표 1] 의사결정나무의 구성요소

구성요소 설명
뿌리 마디 (Root Node) 분할의 시작점으로 첫 번째 분할 규칙이 명시된다.
중간 마디 (Internal Node) 뿌리 마디로부터 최종 마디 전까지 분할된 부분으로 하위 마디로 뻗어갈 분할 규칙이 명시된다.
끝 마디 (Terminal Node) 리프 (Leaf)라고도 하며, 최종적으로 결정된 예측값이 기입된다.
가지 (Branch) 하나의 마디로부터 끝 마디까지 연결된 일련의 마디들을 의미한다.

 

 의사결정나무는 예측하고자 하는 목표변수의 데이터 타입에 따라 분류나무 (Classification Tree)와 회귀나무 (Regression Tree)로 분류할 수 있는데, 목표변수의 데이터 타입이 범주형인 경우 분류나무, 수치형인 경우 회귀나무라고 한다. 분류나무의 경우 끝 마디에서 각 클래스의 비율을 비교하여 가장 높은 비율을 갖는 클래스를 결정하고, 회귀나무의 경우 끝 마디에 있는 관측치들의 평균값으로 계산된다. 

 

 

 의사결정나무의 가장 큰 특징은 계층적 구조 (Hierarchical Structure)로 이루어져 있기 때문에 예측이 어떻게 이뤄지는지 비교적 명확하게 이해할 수 있다는 점이다. 따라서, 의사결정나무로 예측된 결과에 대해 비교적 상세한 설명이 가능하다. 이렇게 모형이 예측하는 방식을 분석자가 볼 수 있는 모형을 화이트 박스 (White Box) 모형이라고 하며, 반면 신경망과 랜덤 포레스트와 같이 예측 방식을 이해하기 어렵고, 왜 이러한 예측 결과를 만들어냈는지 설명하기 어려운 모형을 블랙 박스 (Black Box) 모형이라고 한다. 의사결정나무의 장단점을 정리하면 다음과 같다.

[표 2] 의사결정나무 모형의 장단점

장점 모형을 시각화하여 이해하기 쉽고 해석하기 쉽다.
모형 생성을 위한 전처리 과정이 필요 없다. 
모형 스스로 중요한 변수를 선택하는 변수 선택 (Feature Selection) 기능이 있다.
단점 나무의 일반화 성능이 좋지 않아 쉽게 과잉적합 되기 쉽다.
데이터의 작은 차이로 인해 완전히 다른 나무가 생성될 수 있기 때문에 모형이 다소 불안정하다.
계층적 구조로 인해 중간에 오차가 발생하면 다음 단계에도 오차가 계속 전파된다.

 

 

 

분할기준

 의사결정나무에서 나무는 특정 기준에 따라 분할되며, 가지가 분리됨으로써 성장한다. 즉, 뿌리 마디에서 시작한 나무는 새로운 마디를 생성하면서 매번 최적의 분할변수와 분할점을 찾게 된다. 분할변수란 우리가 사용하고자 하는 독립변수 (x1x2, …, xq) 중 하나를 의미하고, 분할점은 선택된 분할변수 안에서 분할되는 특정값 또는 수준을 의미한다. 의사결정나무는 이러한 분할변수와 분할점을 자동으로 결정하기 때문에 자연스럽게 변수 선택 (Feature Selection) 기능을 수행하게 된다.

 

(1) 회귀나무의 분할기준

수치 예측을 하는 회귀나무의 최종 예측값은 끝 마디에 속한 관측치의 평균값이다. 즉, 성능이 좋은 수치 예측 모형을 만들기 위해서는 이러한 예측값과 실제값의 차이가 최소가 되어야 하므로 MSE와 같은 오차 지표를 통해 분할기준을 찾는다. 구체적으로는 예측값과 실제값 차이의 제곱 값인 MSE가 최소가 되는 분할변수와 분할점을 찾기 위해 모든 독립변수와 분할 가능점을 넣어가면서 최적의 분할변수와 분할점을 찾게 된다. 수치 예측을 위한 종속변수 Y에 대한 MSE는 다음과 같이 표현할 수 있다.

 

(2) 분류나무의 분할기준

 분류 예측을 하는 분류나무의 경우 끝 마디에서 각 클래스의 비율을 비교하여 가장 큰 비율을 차지하는 클래스로 종속변수를 예측한다. 분류나무는 각 마디에서 불순도 또는 순수도를 측정하여 불순도가 낮아지거나 순수도가 높아지는 방향으로 마디를 형성해 나간다. 여기에서 불순도 (Impurity)란 특정 마디에 얼마나 다양한 범주들이 포함되어 있는지 나타내는 지수이고, 순수도 (Purity)는 거꾸로 특정 마디에 하나의 범주가 얼마나 포함되어 있는지 나타내는 지수인데, 두 가지는 결국 동일한 의미를 반대로 표현한 것이다.

분류나무는 이 중에서 불순도의 개념을 주로 사용하며, 불순도를 측정하는 대표적인 지표로는 엔트로피 지수와 지니 지수가 있다. 

 

1) 엔트로피 지수

 엔트로피 (Entropy)란 원래 열역학에서 무질서도를 의미하는 지표로서 여기에서는 얼만큼의 다양한 정보가 내포되어 있는지를 표현하는 의미로 사용한다. 즉, 엔트로피가 클수록 불순도가 커지고, 정보가 다양하게 분포되기 때문에 분류가 어려워진다. 따라서 분류나무는 불순도를 낮추기 위해서 엔트로피 지수의 감소량이 커지는 방향으로 하위 마디를 생성하게 된다. 한편, 불순도가 감소하는 것을 정보이론에서는 정보 획득 (Information Gain)이라 하는데, 이 관점에서 설명하면 분류나무는 정보 획득이 커지는 방향으로 나무의 하위 마디가 생성된다고 할 수 있다. 엔트로피 지수의 일반적인 모형은 다음과 같다. 

 

2) 지니 지수

 지니 지수 (Gini Index)는 샘플을 무작위로 선택할 경우 잘못된 클래스로 분류될 확률 또는 정도를 의미하는 지표이다. 지니 지수는 0에서 1 사이의 값을 갖게 되는데, 0은 모든 요소가 특정 클래스에 속한다는 것을 뜻하고, 1에 가까울수록 요소들이 여러 클래스에 분산되어 있음을 나타낸다. 따라서, 지니 지수를 활용한 의사결정나무 모형은 지니 지수를 감소시켜주는 방향으로 하위 마디가 생성된다. 지니 지수의 일반적인 모형은 다음과 같다. 

 참고로, Scikit-Learn에서 제공하는 의사결정나무 함수는 ‘criterion’이라는 인자를 통해 엔트로피 지수를 사용할지, 지니 지수를 사용할지 결정할 수 있다. 기본적으로 어떤 지수를 통해 모형을 생성해도 성능의 차이가 크지 않지만, 지니 지수는 계산이 조금 더 빠르고, 엔트로피 지수는 조금 더 균형 잡힌 트리를 만들어 준다는 장점을 가지고 있다. 

 

[2] 정지기준과 가지치기

 이론적으로 의사결정나무는 불순도를 최소화 하기 위해 완전한 분류가 이루어질 때까지 나무를 성장시킬 수 있다. 그러나, 이렇게 거대하고, 복잡한 의사결정나무 모형은 새로운 데이터 예측에 적용하기 어려운 과잉적합 문제를 발생시킬 수 있다. 정지기준과 가지치기는 이렇게 의사결정나무 모형이 과대하게 커지는 것을 방지함으로써 일반화된 성능을 가질 수 있도록 보완해주는 역할을 해주게 된다. 

 

(1) 정지기준

 정지기준이란 의사결정나무 모형이 과잉적합 되지 않도록 가지가 분할되는 것을 정지시키는 기준을 설정하는 것이다. 대표적인 의사결정나무의 정지기준들은 다음과 같다. 

  1. 마디를 분할하기 위한 최소한의 샘플 수를 지정한다. 
  2. 데이터 세트에서 고려할 최대 변수의 개수를 지정한다.
  3. 끝 마디가 되기 위한 최소한의 샘플 수를 지정한다.
  4. 끝 마디의 최대 개수를 지정한다.

 

(2) 가지치기

 가지치기 (Pruning)란 의사결정나무의 가지를 잘라내어 모형을 단순화하는 과정을 의미한다. 가지치기에는 사전 가지치기와 사후 가지치기 2가지 방식이 있다. 

  1. 사전 가지치기 (Pre-Pruning): 미리 의사결정나무의 최대 깊이를 설정하여 더 이상 분류가 필요 없거나, 최대 깊이에 도달하면 더 이상 분할시키지 않는 방식으로 적절한 규모의 나무를 생성한다. 
  2. 사후 가지치기 (Post-Pruning): 성장이 끝난 의사결정나무에 대해 불필요한 노드와 가지를 선별하여 해당 가지를 제거함으로써 적정한 규모의 의사결정나무를 만드는 방식이다. 

그러나, Scikit-Learn의 의사결정나무 함수는 사전 가지치기만을 지원하며, max_depth라는 인자를 통해 설정할 수 있다.

 

[3] 대표 알고리즘

다음은 의사결정나무의 대표적인 3가지 알고리즘이다. 

  1. CART: 의사결정나무를 형성하는 데 있어서 가장 보편적으로 사용하는 알고리즘이다. 이진 분리만을 지원하며, 독립변수의 척도 유형과 상관없이 적용할 수 있다는 장점으로 널리 사용되고 있다.
  2. C5.0: 엔트로피 지수를 사용하며 이진 및 다진 분리가 가능한 의사결정나무 알고리즘이다. 명목형 종속변수만을 지원하는 단점이 있지만, 가장 정확한 분류를 만들어 주는 알고리즘으로 평가받는다.
  3. CHAID: 카이제곱 검정을 적용하여 적당한 수준에서 나무의 성장을 중단시키며 이진 분리를 지원하는 알고리즘이다. 분할기준으로는 카이제곱 통계량(이산형) 또는 F-검정(연속형)을 사용한다. CART 알고리즘과 마찬가지로 척도와 관계없이 사용할 수 있다.

 

아래 실습을 통해서는 Scikit-Learn 라이브러리의 의사결정나무 함수는 CART 알고리즘을 사용하여 분류 예측을 진행해 보겠다.

 

연습

 

1) 변수 지정 및 전처리

모형에 이용할 독립변수와 종속변수를 선택하고 모형 학습 및 평가를 위한 데이터 분할, 그리고 샘플링 과정을 거친다.

#1. 모듈 및 함수 불러오기
import pandas as pd
from sklearn.model_selection import train_test_split
from imblearn.over_sampling import SMOTE

#2. 데이터 불러오기 
df = pd.read_csv('Data.csv', encoding = 'cp949')

#3. 변수 지정(독립변수/종속변수)
X=df[['변수1', '변수2', '변수3', '변수4', '변수5', '변수6', '변수7', '변수8간','변수9', '변수10'
Y=df['이진변수']

#4. 데이터 분할
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)

#5. 오버 샘플링 
smote = SMOTE(random_state=0)
X_train, Y_train = smote.fit_sample(X_train, Y_train)

▶ 기본적인 작업으로 데이터를 불러오고, 독립변수와 종속변수를 지정한 뒤 학습용 데이터 세트와 평가용 데이터 세트로 분할하였다. 그리고, 데이터 불균형 문제를 해결하기 위해 SMOTE 함수를 사용하여 오버 샘플링을 적용했다. 참고로 의사결정나무 모형에서는 데이터 표준화와 같은 전처리 작업이 필요 없으므로 생략했다.

 

2) 모형 학습 및 예측

#1. 모듈 및 함수 불러오기
from sklearn.tree import DecisionTreeClassifier

#2. 모형 생성
model = DecisionTreeClassifier(random_state=0, max_depth = 3)

#3. 모형 학습 및 예측
model.fit(X_train, Y_train)
Y_pred = model.predict(X_test)
print('평가용 데이터 세트에 대한 예측값\n', Y_pred)

▶ DecisionTreeClassifier( ) 함수를 사용하여 의사결정나무 모형을 생성한다. 인자 max_depth는 나무의 최대 깊이를 제한하는 일종의 사전 가지치기 옵션이고, 기본값은 None으로 설정되어 있다. max_depth를 지정하지 않으면 자칫 과잉적합 된 모형이 생성될 수 있으므로 나무의 깊이를 3으로 설정했다. 그리고, 이 예제 코드에는 나오지 않지만 criterion이라는 인자를 통해 불순도 측정방식으로 지니 지수나 엔트로피 지수를 선택할 수 있으며, 기본값은 지니 지수로 지정되어있다. 본 실습에선 두 지수 간의 성능상 차이는 없어서 기본값으로 지정하였다.  

DecisionTreeClassifier( ) 함수의 자세한 설명은 아래 URL에서 확인할 수 있다.

https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html

 

3) 모형 평가

의 코드들은 간단하고 앞선 게시글에서 반복해서 했으니 생략하겠다.

 

4) 변수 중요도 출력

feature_name = X.columns
feature_importances = model.feature_importances_
sorted(zip(feature_importances, feature_name), reverse=True)

 

5) 모형의 시각화

 의사결정나무의 장점 중 하나는 나무 형태의 모형을 시각적으로 보여줄 수 있다는 것이다. 이를 위해서는 파이썬 외부 라이브러리인 Graphviz를 사용해야 하는데, Graphviz를 설치한 뒤 파이썬과 연동할 수 있는 라이브러리를 별도로 설치해줘야 한다. 다음의 순서에 따라 Graphviz를 설치해보자.

- Graphviz 소프트웨어 설치 

아래의 URL에 접속하여 graphviz-2.38.msi를 다운받아 설치한다. 

https://graphviz.gitlab.io/_pages/Download/Download_windows.html

 

- 환경변수 설정

▶ Graphviz를 파이썬에 연결하려면 추가적인 환경변수 설정이 필요하다. 이를 위해 [내 PC] 우클릭-[속성]-[고급 시스템 설정]-[환경변수]를 클릭하여 환경변수 창을 연다. 그다음 사용자 변수의 [Path]-[편집]-[새로 만들기]를 클릭하여 ‘Graphviz 설치 경로\bin’을 추가한다. 마찬가지로 시스템 변수의 [Path]-[편집]-[새로 만들기]를 클릭하여 ‘Graphviz 설치 경로\bin\dot.exe’를 추가한다. 

 

- Graphviz 라이브러리 설치

아나콘다 프롬프트를 관리자 권한으로 실행하여 다음의 코드를 입력 실행하고, 주피터 노트북을 재가동한다.

그 후 아래 코드를 입력한다.

#1. 모듈 및 함수 불러오기
import graphviz
from sklearn.tree import export_graphviz

#2. tree.dot 파일 생성
export_graphviz(model, out_file=‘tree.dot’, class_names= ['0', '1'], \
                feature_names = feature_name, impurity=True, filled=True)

#3. tree.dot 파일 읽기 
with open(‘tree.dot’, encoding = 'utf-8') as f:
    dot_graph = f.read()
graphviz.Source(dot_graph)

 


 

This post was written based on what I read and studied the book below.

http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9791195511747

댓글