본문 바로가기
기계학습(ML)/Tree based Model

n221 Decision Trees, gini, entropy

by kiimy 2021. 6. 19.
728x90
  • 사이킷런 파이프라인(pipelines) 을 이해하고 활용 할 수 있습니다.
  • 사이킷런 결정트리(decision tree) 를 사용할 수 있습니다.
  • 결정트리의 특성 중요도(feature importances) 를 활용할 수 있습니다.
  • 결정트리 모델의 장점을 이해하고 선형회귀모델과 비교할 수 있습니다.

모든 binary binary 변수는 다음과 같은 규칙을 따릅니다. 0 : No / 1 : Yes

*지도학습 

==> train set을 학습 알고리즘에 넣은 다음 가설함수 도출

           train set

           알고리즘

price -> 가설함수 -> 추정치( predict )

 

1. Train data ==> train / val set으로 나눔

# profiling

! pip install pandas-profiling==2.*
train.profile_report()

train, val = train_test_split(train, train_size=0.80, test_size= 0.20,

                                  stratify= train[target], random_state=2) 
'''
stratify: default=None,

classification을 다룰 때 매우 중요한 옵션값 stratify 값을 target으로 지정해주면 각각의 class 비율(ratio)을

train / validation에 유지해 줍니다. (한 쪽에 쏠려서 분배되는 것을 방지합니다) 만약 이 옵션을 지정해 주지 않고 classification 문제를 다룬다면, 성능의 차이가 많이 날 수 있습니다.
'''

2. target 비율 확인

class 확인 / 분류문제인지 회귀문제인지( 0, 1 이면 분류문제로 확인 )

비율이 한쪽으로 많이 크다면 불균형한 분류문제( imbalanced )

==> 검증 데이터의 정확도 score(X_val, y_val) 와 기준모델의 다수 범주(0) 비율과 비슷하다면

        확실히 과적합이고 대부분 0으로 예측했다고 볼 수 있다.

 

3. 데이터 타입 확인하고 (dtypes) 해당 타입이 범주형인지 이진형인지 확인

 

4. 중복된 특성 확인 ( train.T.duplicated() )

 

5. 너무 많은 범주를 가지는 카테고리 특성들이 있는지 cardinality 확인 

unique()는 데이터에 고유값들이 어떠한 종류들이 있는지 알고 싶을때 사용하는 함수

nunique()는 데이터에 고유값들의 수를 출력해주는 함수 = label이 다양하면 높게나오는거지

value_counts()는 값별로 데이터의 수를 출력해주는 함수

train.describe( exclude= 'number' )

selected_cols = df.select_dtypes(include=['number', 'object'])

selected_cols.nunique() # 특성별 카디널리티 리스트

## 중복도가 ‘낮으면’ 카디널리티가 ‘높다’고 표현한다.

    중복도가 ‘높으면’ 카디널리티가 ‘낮다’고 표현한다.

==> 특성개수 파악

ex) 주민등록번호 같은 경우는 중복되는 값이 없으므로 카디널리티가 높다고 할 수 있다.

     이에 비해 이름같은 경우는 ‘주민등록번호에 비해’ 중복되는 값이 많으므로,

     이름은 ‘주민등록번호에 비해’ 카디널리티가 낮다고 할 수 있다.

 

6. Feature Engineering

* Pipeline

from sklearn.pipeline import make_pipeline

pipe= make_pipeline(
            OneHotEncoder(),
            SimpleImputer(),
            StandardScaler(),
            ogisticRegression(n_jobs=-1) )

pipe.named_steps
# ==> 유사 딕셔너리 객체(dictionary-like object)로 파이프라인 내 과정에 접근 가능
import matplotlib.pyplot as plt

model_lr = pipe.named_steps['logisticregression']
enc = pipe.named_steps['onehotencoder']
encoded_columns = enc.transform(X_val).columns
coefficients = pd.Series(model_lr.coef_[0], encoded_columns)
plt.figure(figsize=(10,30))
coefficients.sort_values().plot.barh();

* 결정트리 ( Decision Trees )

특성들을 기준으로 샘플을 분류해 나가는데 그 형태가 나무의 가지가 뻗어나가는

모습과 비슷해서 결정트리라는 이름을 가지고 있다.(= node들의 복잡성 즉, impurity가 낮은 방향으로 tree 생성)

비선형, 비단조(non-monotonic), 특성상호작용(feature interactions) 특징을 가지고 있는 데이터 분석에 용의

* 질문, 말단의 정답 = 노드 ( Node )

* 노드를 연결하는 선 = Edge

* 분류가 끝난 것 = leaf

  • 결정트리의 각 노드(node)는 뿌리(root)노드, 중간(internal)노드, 말단(external, leaf, terminal) 노드로 나뉠 수 있습니다.
  • 회귀, 분류 모두 적용 가능
  • 데이터를 분할해 가는 알고리즘

분류 과정은 새로운 데이터가 특정 말단 노드에 속한다는 정보를 확인한 뒤 말단노드의 빈도가가장

높은 범주로 데이터를 분류

==> 결과 노드(leaf) 안에서 섞여있는 정도가 낮은(impurity) tree를 만드는 것이 목표

* 결정트리를 학습하는 것은 노드를 어떻게 분할하는가

==> gini, Entropy

비용함수를 정의하고 그것을 최소화 하도록 분할하는 것 = 트리모델 학습 알고리즘

엔트로피는 기계학습에서는 모델의 예측값과 라벨간의 무질서함의 정도를 측정합니다.
무질서함이 없으면 예측값과 라벨이 똑같다는 것이고, 무질서함이 최대값이면 완전히 다르다는 것으로
해석할 수 있습니다. 무질서함을 측정한다는 것이 좀 이상하지만 두 값들이 얼마나 다르냐를 측정하는
것입니다. = entropy 는 예측하기 쉬운 일에서보다, 예측하기 힘든일에서 더 높다.

*불순도(impurity) 라는 개념은 여러 범주가 섞여 있는 정도 ( 지표 = gini index, entropy )

  • (45%, 55%)인 샘플(두 범주 수가 비슷)은 불순도가 높은 것이며 ( gini impurity, entropy 높다 )
  • (80%, 20%)인 샘플이 있다면 상대적으로 위의 상태보다 불순도가 낮은 것 입니다.(순수도(purity)는 높음)
  • ==> ( gini impurity, entropy 낮다 )
  • 확률이 비등비등하면 entropy 높고 너무 당연하면 entropy는 낮다

* 중요도정보( gini impurity )(= 분류 틀릴 가능성==0 이면 순수도가 높다)

= 중요도는 노드들의 지니불순도, entropy를 가지고 계산

# node가 중요할 수록 불순도는 크게 감소

==> 한 특성 값을 기준으로 분리가 되기 때문에 불순도를 크게 감소하는데 사용된 특성이 중요도가 크다

*엔트로피 - 데이터를 split함으로써 엔트로피 낮아짐 ==> 데이터가 깔끔해짐

* information gain - 특정한 특성을 사용해 분할 했을 때 엔트로피 감소량

==> node들의 복잡성을 계산

  • 분할에 사용할 특성이나 분할지점(값)은 타겟변수를 가장 잘 구별해 주는
  • (불순도의 감소가 최대가 되는, 정보획득이 가장 큰)것을 선택합니다.
  • 정보획득(Information Gain)은 특정한 특성을 사용해 분할했을 때 엔트로피의 감소량을 뜻합니다

분할에 사용할 특성 or 분할지점(값)은 target변수를 가장 잘 구별해주는 것 선택

==> 불순도의 감소가 최대 / imformation gain 큰것 ( entropy, gini 작은것 ) => 확실정보획득

* 위 기준으로 Initial split( 확실 정보 )

from sklearn.tree import DecisionTreeClassifier

* 과적합 해결 (= 하이퍼 파라미터 튜닝 n224에서 ) 

==> 복잡도를 낮추어 일반화 유도

* 특성 중요도 ( feature importance )

==> 모델.feature_importances_

전체 트리를 살펴보는 것은 어려울 수 있으니, 대신 트리가 어떻게 작동하는지 요약하는 속성들을 사용할 수 있다

선형모델= 회귀 계수

분류모델= 특성중요도 == 항상 양수 값을 가짐 ( 얼마나 일찍 and 자주 분기에 사용되는지 결정 )

*주의*
어떤 특성의 feature_importance_ 값이 낮다고 해서 이 특성이 유용하지 않다는 뜻은 아닙니다.
단지 트리가 그 특성을 선택하지 않았을 뿐이며 다른 특성이 동일한 정보를 지니고 있어서일 수 있습니다.

DecisionTreeRegressor(그리고 모든 다른 트리 기반 회귀 모델)는 외삽extrapolation
, 즉 훈련 데이터의 범위 밖의 포인트에 대해 예측을 할 수 없습니다. 
enc = pipe.named_steps['onehotencoder']
encoded_columns = enc.transform(X_val).columns

model_dt = pipe.named_steps['decisiontreeclassifier']

importances = pd.Series(model_dt.feature_importances_, encoded_columns)
'''
model_dt.feature_importances_
특성 중요도:
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.01
  0.048 0. 0. 0.002 0. 0. 0. 0. 0. 0.727 0.046
  0. 0. 0.014 0. 0.018 0.122 0.012 0. ]
'''
# 각 특성에 대해 0은 전혀 사용되지 않았다는 뜻이고 1은 완벽하게 타깃 클래스를 예측했다는 뜻

* 특성상호작용 ( 데이터를 수정해도 트리에 지장 X)

==> tree모델은 전처리 과정이 필요가 없음( 전처리 영향이 없음 = StandardScaler X )

정보의 균일도만 신경쓰면 되므로 특별한 경우를 제외하고는 각 피처의 스케일링과 정규화
같은 전처리 작업이 필요없다.

==> 회귀분석에서는 서로 상호작용이 높은 특성들이 있으면 개별 계수를 해석하는데

어려움이 있어 학습이 올바르게 되지 않을 수 있음 but 트리모델은 이런 상호작용을 자동으로 걸러냄

*장점*
만들어진 모델을 쉽게 시각화할 수 있어서 비전문가도 이해하기 쉽습니다(비교적 작은 트리일 때).
그리고 데이터의 스케일에 구애받지 않습니다. 각 특성이 개별적으로 처리되어 데이터를 분할하는 데
데이터 스케일의 영향을 받지 않으므로 결정 트리에서는 특성의 정규화나 표준화 같은 전처리 과정이 필요 없습니다. 특히 특성의 스케일이 서로 다르거나 이진 특성과 연속적인 특성이 혼합되어 있을 때도 잘 작동합니다.

*단점*
사전 가지치기를 사용함에도 불구하고 과대적합되는 경향이 있어 일반화 성능이 좋지 않다는 것
==> 앙상블 방법을 단일 결정 트리의 대안으로 흔히 사용

 

*seaborn

728x90

댓글