Tree based Machine Learning의 기본 Decision tree.
데이터 분할하는 Algorithm으로 분류와 회귀문제 모두 적용 가능.
선형모델과 달리, Decision Tree 모델은 특성들을 기준으로 샘플을 분류해 나가는 형태.
각 특성들의 수치를 가지고 질문을 통해 정답 클래스를 찾아가는 과정, 여기서 질문이나 말단의 정답을 Node(노드)라고 하며 그 Node를 연결하는 선을 Edge(엣지)라고 한다.
- 결정트리는 분류(Classifier)와 회귀(Regressor)문제 모두 적용 가능합니다.
- 결정트리는 데이터를 분할해 가는 알고리즘입니다.
- 분류 과정은 새로운 데이터가 특정 말단 노드에 속한다는 정보를 확인한 뒤 말단노드의 빈도가 가장 높은 범주로 데이터를 분류한다.
결정트리의 각 노드(node)
- ROOT Node : 뿌리노드
- Internal Node: 중간노드
- Leaf Node: external, leaf, terminal -(더이상 가지가 뻗어나갈 수 없는 단계) 말단 노드로 나뉜다.
Node 를 나누는 Algorithm : 지니불순도 & 엔트로피 ; IG
결정트리의 비용함수를 정의하고 그것을 최소화 하도록 분할하는 것이 트리모델 학습 알고리즘
- 지니불순도(Gini Impurity or Gini Index): = 1 -( the probability of "Yes")^2 - (the probability of "No")^2 = 1 - (N(Yes)/(N(Yes)+N(No)))^2 - (N(No)/(N(Yes)+N(No)))^2
엔트로피(Entropy)는 불순도(Impurity)를 수치적으로 나타낸 척도.
엔트로피가 높다 = 불순도가 높다
엔트로피가 낮다 = 불순도가 낮다 (good)
엔트로피가 1이면 불순도가 최대. 즉, 한 범주 안에 서로 다른 데이터가 정확히 반반 있다는 뜻.
엔트로피가 0이면 불순도는 최소. 한 범주 안에 하나의 데이터만 있다는 뜻입니다.
엔트로피를 구하는 공식은 아래와 같다.
- 엔트로피(Entropy): H =∑(사건발생확률)⋅log2(1/사건발생확률)=∑i(pi) log2(1/pi)=−∑i(pi) log2(pi)
Information Gain ; IG
- 특정 속성을 기준으로 Example들을 구분하게 될때 '감소되는 Entrophy의 양'
- 정보획득(Information Gain)은 특정한 특성을 사용해 분할했을 때 엔트로피의 감소량
- IG(T,a) = H(T) - H(T|a) = 분할전 노드 불순도 - 분할 후 자식노드 들의 불순도 = entropy(parent) - [weighted average] entropy(children)
- IG는 클수록 좋다.
가지치기(Pruning)
Decision Tree는 특성상 과적합이 잘 일어남, 이를 줄이기 위해 복잡도를 낮춰야 한다. 복잡도를 낮추는것을 Pruning(가지치기)라고 한다. 아래의 HyperParameter 조절
- min_sample_leaf
- min_sample_split (min_sample_split = 10이면 한 노드에 10개의 데이터가 있다면 그 노드는 더 이상 분기를 하지 않습니다.)
- max_depth (max_depth = 4이면, 깊이가 4보다 크게 가지를 치지 않습니다.)
즉, 최대 깊이(max_depth)나 터미널 노드의 최대 개수(min_sample_leaf), 혹은 한 노드가 분할하기 위한 최소 데이터 수(min_sample_split )를 제한하는 것.
Decision Tree Process
Yes or No data (이진분류문제일때) | Numeric Data (회귀문제일때) |
Gini Impurity 값을 모두 계산 | Numeric data를 순서대로 정령 |
노드 자체의 값이 가장 낮으면 더이상 가지치기를 하지않고 Leaf node로 남는다 | 인접한 모든 numeric data를 평균내어 계싼 |
데이터 분리가 개선되면 Gini Impurity값이 가장 낮은 항목의 데이터 분리를 실행 | 각 평균값들의 Impurity values계산 |
Python - Decision tree classifier
1. 라이브러리 불러오기
from sklearn.tree import DecisionTreeClassifier
from category_encoders import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.pipeline import make_pipeline
2. 파이프라인을 이용하여 Decision Tress Classifier
결정트리에서는 StandardScaler는 도움이 되지 않기 때문에 제외하고 학습
pipe = make_pipeline(
OneHotEncoder(use_cat_names=True),
SimpleImputer(),
DecisionTreeClassifier(random_state=1, criterion='entropy'))
pipe.fit(X_train, y_train)
print('훈련 정확도: ', pipe.score(X_train, y_train))
print('검증 정확도: ', pipe.score(X_val, y_val))
훈련 정확도: 0.9908667674880646
검증 정확도: 0.7572055509429486
>>>>> 훈련정확도 99%라는 과접합이 발생.
3. 검증값으로 훈련 정혹도와 다른점 확인하기
y_val.value_counts(normalize=True)
0 0.761001
1 0.238999
Name: vacc_h1n1_f, dtype: float64
4. 과적합 해결을 위한 하이퍼 파라미터 사용
1) 말단 노드(external node)에 최소한 존재해야 하는 샘플들의 수 지정
pipe = make_pipeline(
OneHotEncoder(use_cat_names=True),
SimpleImputer(),
DecisionTreeClassifier(min_samples_leaf=10, random_state=2))
pipe.fit(X_train, y_train)
print('훈련 정확도', pipe.score(X_train, y_train))
print('검증 정확도', pipe.score(X_val, y_val))
훈련 정확도 0.8577528689618361
검증 정확도 0.8029889692800379
2)max_depth 제한
pipe = make_pipeline(
OneHotEncoder(use_cat_names=True),
SimpleImputer(),
DecisionTreeClassifier(max_depth=6, random_state=2)
)
pipe.fit(X_train, y_train)
print('훈련 정확도', pipe.score(X_train, y_train))
print('검증 정확도', pipe.score(X_val, y_val))
훈련 정확도 0.8283367434688491
검증 정확도 0.8269481674771676
3) GridSearchCV / RandomizedSearchCV 이용 최적의 하이퍼파라미터 지정
- GridSearchCV: 검증하고 싶은 하이퍼파라미터들의 수치를 정해주고 그 조합을 모두 검증합니다.
- RandomizedSearchCV: 검증하려는 하이퍼파라미터들의 값 범위를 지정해주면 무작위로 값을 지정해 그 조합을 모두 검증합니다.
5. Feature Importance 특성 중요도
선형모델에서는 특성과 타겟의 관계를 확인하기 위해 회귀 계수(coefficients)를 살펴보지만 결정트리에서는 대신 특성중요도를 확인한다.
회귀계수와 달리 특성중요도는 항상 양수값을 가지며. 이 값을 통해 특성이 얼마나 일찍 그리고 자주 분기에 사용되는지 결정된다.
model_dt = pipe.named_steps['decisiontreeclassifier'] # 파이프라인에서 스텝 가지고 나오기
importances = pd.Series(model_dt.feature_importances_, encoded_columns) # 중요특성 따로 데이터프레임으로 만들어주기
plt.figure(figsize=(10,30)) # 그래프로 만들기
importances.sort_values().plot.barh();
6. 최종 모델 학습
위의특성중요도를 반영한 데이터 features와 최적의 하이퍼파라미터를 적용시킨 모델을 test set에 학습시킨다.
7. 트리모델 시각화 하기
1) graphviz 모듈 설치 및 라이브러리 불러오기
# graphviz 설치방법: conda install -c conda-forge python-graphviz
import graphviz
from sklearn.tree import export_graphviz
2) 파이프라인에서 모델과 인코더 추출하여 그래프 데이터셋 만들고 시각화.
model_dt = pipe.named_steps['decisiontreeclassifier']
enc = pipe.named_steps['onehotencoder']
encoded_columns = enc.transform(X_val).columns
dot_data = export_graphviz(model_dt
, max_depth=3
, feature_names=encoded_columns
, class_names=['no', 'yes']
, filled=True
, proportion=True)
display(graphviz.Source(dot_data))
Python- Decision tree Regressor
1. 라이브러리 불러오기
from ipywidgets import interact
from sklearn.tree import DecisionTreeRegressor, export_graphviz
2. 인터랙션함수에 모델 대입 및 학습
def thurber_tree(max_depth=1):
tree = DecisionTreeRegressor(max_depth=max_depth)
tree.fit(X_thurber, y_thurber)
print('R2: ', tree.score(X_thurber, y_thurber))
ax = thurber.plot('mobility', 'density', kind='scatter', title='Thuber')
ax.step(X_thurber, tree.predict(X_thurber), where='mid')
plt.show()
display(show_tree(tree, colnames=['mobility']))
interact(thurber_tree, max_depth=(1,6,1));
max_depth = 1인 경우는 선형회귀 보다 성능이 안 좋아 보이지만 max_depth를 더할 수록 선에 적합이 되어 비선형 데이터를 학습할 수 있음을 시각적으로 확인할 수 있다.
특성 상호작용
결정트리모델은 선형모델과 달리 비선형, 비단조(non-monotonic), 특성상호작용(feature interactions) 특징을 가지고 있는 데이터 분석에 용의합니다.
- 단조(Monotonic), 비단조(Non-monotonic) 함수
- 특성상호작용
- 특성상호작용은 특성들끼리 서로 상호작용을 하는 경우를 말합니다. 회귀분석에서는 서로 상호작용이 높은 특성들이 있으면 개별 계수를 해석하는데 어려움이 있고 학습이 올바르게 되지 않을 수 있습니다. 하지만 트리모델은 이런 상호작용을 자동으로 걸러내는 특징이 있습니다