pythonML

[pythonML] 결정 트리 (Decision Tree)

독립성이 강한 ISFP 2022. 3. 20. 22:33
728x90
반응형

# 지도학습: 레이블(Label)이 있는 데이터가 주어진 상태에서 학습하는 머신러닝 방식

 

# 분류

  • 나이브 베이즈(Naive Bayes) : 베이즈 통게와 생성 모델에 기반
  • 로지스틱 회귀(Logistic Regression) : 독립변수와 종속변수의 선형 관계성에 기반
  • 결정 트리(Decision Tree) : 데이터 균일도에 따른 규칙 기반
  • 서포트 벡터 머신(Support Vector Machine) : 개별 클래스 간의 최대 분류 마진을 효과적으로 찾아줌
  • 최소 근접 알고리즘(Nearest Neighbor) : 근접 거리를 기준으로 함
  • 신경망(Neural Network) : 심층 연결 기반의 신경망
  • 앙상블(Ensemble) : 서로 같은/다른 머신러닝 알고리즘을 결합한 앙상블

 

 

# 결정트리(Decision Tree) 

 

  • 규칙 조건에 따라 서브 트리가 계속 생성됨 BUT 서브트리가 계속해서 생기게 되면 트리가 복잡해지고 이는 과적합으로 이어지기 쉬움 즉, 트리의 깊이가 깊어질수록 결정 트리의 예측 성능이 저하될 가능성이 높음
  • 최대한 적은 노드로 높은 예측 정확도를 가지려면 => 최대한 많은 데이터들이 해당 분류에 속하도록 노드의 규칙이 정해져야 함. 이를 위해 어떻게 트리를 분할 할 것인가?=> 최대한 균일한 데이터 세트를 구성할 수 있도록 분할한다. (균일한 데이터를 먼저 선택하기)
  • 균일도를 측정하는 방법 : 엔트로피를 이용한 정보 이득 (정보이득이 높을 수록 균일도 높음), 지니계수(0에 가까울수록 균일도가 높음, 1에 가까울수록 낮음)

 

장점: 쉽다, 직관적이다. (균일도만 생각하면 됨/ 스케일링과 정규화 같은 전처리 필요X)

단점: 과적합 주의. (트리의 크기를 사전에 제한하는 튜닝 필요O)

 

# 결정 트리(Decision Tree) 파라미터

  • min_samples_split : 노드를 분할하기 위한 최소한의 샘플 데이터 , default = 2 ( 작게 설정할 수록 분할되는 노드가 많아져서 과적합 가능성 증가 )
  • min_samples_leaf : 리프 노드가 되기 위한 최소한의 샘플 데이터 수, 비대칭적 데이터의 경우 특정 클래스의 데이터가 극도로 작을 수 있기 때문에 작게 설정해 주어야 한다. ( 과적합 제어 용도 )
  • max_features : 최적의 분할을 위해 고려할 최대 피처 개수, default = None ( 모든 피처를 사용해 분할 수행 ) ( int, float, sqrt = auto, log )
  • max_depth : 트리의 최대 깊이를 규정 , default = None ( 완벽하게 클래스 결정 값이 될 때까지 깊이를 계속 키움 or 노드가 가지는 데이터 개수가 min_samples_split보다 작아질 때까지 계속 깊이를 증가시킴 )
  • max_leaf_nodes : 리프 노드의 최대 개수

 

# 결정트리(Decision Tree)  시각화

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')

# DecisionTree Classifier 생성
dt_clf=DecisionTreeClassifier(random_state=156)

# 붓꽃 데이터를 로딩하고, 학습과 테스트 데이터 셋으로 분리
iris_data=load_iris()
X_train,X_test,y_train,y_test= train_test_split(iris_data.data, iris_data.target, test_size=0.2,random_state=11)

# DecisionTreeClassifer 학습. 
dt_clf.fit(X_train, y_train)
from sklearn.tree import export_graphviz
# export_graphviz() : Graphviz가 읽어 들여서 그래프 형태로 시각화할 수 있는 출력 파일을 생성함

# export_graphviz()의 호출 결과로 out_file로 지정된 tree.dot 파일을 생성함.
export_graphviz(dt_clf, out_file='tree.dot', class_names=iris_data.target_names,
               feature_names=iris_data.feature_names, impurity=True, filled=True)
import graphviz

# 위에서 생성된 tree.dot 파일을 Graphviz 읽어서 Jupyter Notebook상에서 시각화 
with open("tree.dot") as f:
    dot_graph=f.read()
graphviz.Source(dot_graph)

 

 

# 결정트리 피처(feature)의 중요도

-결정트리는 균일도에 기반하기 때문에 어떤 속성을 규칙 조건으로 설정하느냐가 중요=> 몇 개의 피처들이 명확한 규칙트리를 만드는 데 크기 기여하기 때문

( feature_importances_ 함수를 이용하여 피처들의 중요도를 구한다)

import seaborn as sns
import numpy as np
%matplotlib inline

print("Feature importances:\n{0}".format(np.round(dt_clf.feature_importances_,3)))

for name, value in zip(iris_data.feature_names, dt_clf.feature_importances_):
    print('{0} : {1:.3f}'.format(name,value))
    
sns.barplot(x=dt_clf.feature_importances_, y=iris_data.feature_names)
Feature importances:
[0.025 0.    0.555 0.42 ]
sepal length (cm) : 0.025
sepal width (cm) : 0.000
petal length (cm) : 0.555
petal width (cm) : 0.420
petal length의 중요도가 가장 높음

 

# 결정 트리 과적합(Overfitting)

 

*분류할 데이터 생성하는 코드

from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
%matplotlib inline

plt.title("3 Class values with 2 Features Sample data creation")

# 2차원 시각화를 위해서 feature는 2개, 결정값 클래스는 3가지 유형의 classification 샘플 데이터 생성. 
X_features, y_labels = make_classification(n_features=2, n_redundant=0, n_informative=2,
                             n_classes=3, n_clusters_per_class=1,random_state=0)

# plot 형태로 2개의 feature로 2차원 좌표 시각화, 각 클래스값은 다른 색깔로 표시됨. 
plt.scatter(X_features[:, 0], X_features[:, 1], marker='o', c=y_labels, s=25, cmap='rainbow', edgecolor='k')
                    #    X, Y                        color을 y_labels에 따라 다르게 해달라는 의미

 

*위의 데이터들로 결정나무를 이용하여 시각화하는 것

1. 특정한 트리 생성 제약없는 결정 트리의 Decsion Boundary 시각화

from sklearn.tree import DecisionTreeClassifier

# 특정한 트리 생성 제약없는 결정 트리의 Decsion Boundary 시각화.
dt_clf = DecisionTreeClassifier().fit(X_features, y_labels)
visualize_boundary(dt_clf, X_features, y_labels)

너무 정확하게 분류하려다 보니 분할이 자주 일어나서 경계가 매우 많아졌음. 이경우 학습 데이터에만 지나치게 최적화될 수 있음 (과적합 주의)

 

2. min_samples_leaf=6 으로 트리 생성 조건을 제약한 Decision Boundary 시각화

# min_samples_leaf=6 으로 트리 생성 조건을 제약한 Decision Boundary 시각화
dt_clf = DecisionTreeClassifier( min_samples_leaf=6).fit(X_features, y_labels)
visualize_boundary(dt_clf, X_features, y_labels)

이상치에 크게 반응하지 않으면서 좀 더 일반화된 분류 규칙에 따라 분류하였음. 특정한 제약 조건 없는 1번보다 이 모델이 더 뛰어날 가능성이 있다.

728x90
반응형