카테고리 없음

Decision Tree

juju824 2021. 11. 17. 10:29

📌 Decision Tree

- 트리 구조를 이용하여 데이터 사이에 존재하는 패턴을 예측 가능한 규칙들의 조합으로 나타내는 알고리즘 

- 분류 (범주형 레이블)와 회귀 (연속형 레이블)에 모두 사용 가능 

- 각 변수 영역을 재귀적으로 분할하면서 규칙 생성 (If-else)

- 분류의 경우 특성의 영역을 분할하면서 정보 균일도가 높게 하도록 분할하며 회귀의 경우 잔차 제곱합이 최소가 되도록 분할 

 

✔️ 스무고개와 유사

Ex. 어머니가 소고기를 사실까? 

1. 어머니가 오른쪽 시장으로 가면 정육점이 멀어지므로 소고기를 살 확률이 낮아진다. 

2. 어머니가 왼쪽 시장으로 가면 정육점이 가까워지므로 소고기를 살 확률이 높아진다. 

여기서 확률이 높은 2번을 택하고

1. 정육점 사장님이 오늘 할인을 해주시면 소고기를 살 확률이 높아진다. 

2. 정육점 사장님이 오늘 할인을 안해주시면 소고기를 살 확률이 낮아진다. 

...이런식으로 Tree를 만들어서 진행

 

 

✔️ 정보 균일도

엔트로피 entropy를 이용하는 방법과 지니계수 Gini를 이용하는 방법이 있음 

✔️ Entropy

주어진 데이터 집합의 혼잡도 (값 작을수록 데이터 균일)

✔️ 정보이득지수

1-엔트로피 지수 (정보 이득이 높은 속성을 기준으로 분할됨)

✔️ 지니 계수 (Gini)

주어진 데이터 집합의 불순도 (값 작을수록 데이터 균일) , 0에 가까울수록 데이터 평등, 1로 갈수록 불평등 

 

 

 

👾 Example

통증유무, 혈액순환, 동맥경화에 따른 심장 질병 유무를 Decision Tree를 이용하여 분류 

2진 범주형 특성이기 때문에 '숫자'가 아니라 True와 False로 구분 

각 노드의 데이터 개수는 [Yes, No]로 나타난다 

 

아래 표를 통해 확인해보면 X값은 가슴통증, 혈액순환, 동맥경화이며 

👇 우리가 타겟으로 구하고자 하는 예측 값 Y값은 심장질병이다. 👇

  True False
가슴통증 심장질병 [105,39] 심장질병 [34,125]
혈액순환 심장질병 [37,127] 심장질병 [100,33]
동맥경화 심장질병 [92,31] 심장질병 [45,129]

1. NA는 제외하고 계산

2. 가장 좋은 분류 결과를 가지는 노드부터 Tree에 추가

3. 가장 좋은 분류 결과를 가지는 노드가 Root 노드로 지정 

그런데 위에를 보면 모든 X값에 대해서 과반수로 분류가 되었다 -> 뭘 선택해야 할지 모르겠다? 이때, Gini 계수 이용

4. 좋은 분류 결과 계산을 위해서 불순도 Impurity 계산

 

 

Coding을 통해 Decision Tree 알아보기

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer = load_breast_cancer()

x_train, x_test, y_train, y_test = train_test_split(cancer['data'],
                                                    cancer['target'],
                                                    stratify=cancer['target'],
                                                    random_state=0)
cancer['target_names']

👉 train_test_split 통해 학습 및 평가 데이터 분류

 

 

from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier().fit(x_train, y_train)
model.score(x_train, y_train), model.score(x_test, y_test)

#output)  (1.0, 0.9230769230769231)

 

 

학습된 모델에 feature_importances_속성을 통해 어떤 특성이 중요한지를 조회 가능 👇

model.feature_importances_

#output)
array([0.        , 0.0393304 , 0.        , 0.        , 0.00891967,
       0.        , 0.        , 0.01170706, 0.        , 0.        ,
       0.00995684, 0.        , 0.00980366, 0.00999282, 0.        ,
       0.        , 0.        , 0.        , 0.00401385, 0.        ,
       0.        , 0.02958161, 0.72534081, 0.03687207, 0.00931787,
       0.        , 0.        , 0.10516335, 0.        , 0.        ])

 

 

👇 특성 중요도를 시각화해보면

- 문자열을 인덱스로 가질 수 있는 Pandas의 Series로 변환하여 특성 중요도를 시각화할 수 있음 

- 특성 중요도가 0인 데이터를 제외하고 높은 순서대로 시각화 

import pandas as pd
fi = pd.Series(model.feature_importances_, index=cancer['feature_names'])
fi[fi!=0].sort_values(ascending=True).tail(3).plot(kind='barh', figsize=(10, 5))

👉 차례대로 중요도 순서대로 나오게 하면...

fi[fi!=0].sort_values(ascending=False)

#output)
worst perimeter         0.725341
worst concave points    0.105163
mean texture            0.039330
worst area              0.036872
worst texture           0.029582
mean concave points     0.011707
area error              0.009993
radius error            0.009957
perimeter error         0.009804
worst smoothness        0.009318
mean smoothness         0.008920
symmetry error          0.004014
dtype: float64

 

 

Tree로 시각화하기 👇 

from sklearn.tree import export_graphviz
export_graphviz(model3,  out_file='model3.dot',
                feature_names=cancer['feature_names'],
                class_names=cancer['target_names'], impurity=True, filled=True)
                

import graphviz
with open('model3.dot') as f:
data = f.read()
graphviz.Source(data)

시각화된 Tree 좌측
시각화된 Tree 우측

시각화된 Tree가 너무 커서 반으로 쪼개면 위와 같다 

 

 

📌 Decision Tree

장점 단점
✔️ 화이트박스 모델로 모델이 만든 기준과 결과를 해석하고 이해하기 쉬움

✔️ 자료를 가공할 필요가 거의 없으며 범주형 및 연속형 특성 및 문제에 모두 적용 가능

✔️
트리의 깊이 제한 없다면 사용할 수 있는 조건 노드가 많아짐으로써 과대적합 발생가능성 증가

✔️ 트리의 깊이와 결과 노드의 개수 제한하지 않는다면 1-2개 데이터를 분류하는 기준을 만들기 때문에 과대적합 발생 

✔️ 재귀적으로 분할 기준을 만들기 때문에 계산량 많을 수 있음 

✔️ 탐욕 알고리즘 (Greedy Algorithm)으로 인해 최적의 결정 트리를 찾아내지는 않음

✔️데이터가 수진 또는 수평적으로 구분되지 못할 때 결과 나빠짐