220504_TIL / Decision Trees

신두다·2022년 5월 7일
0

TIL

목록 보기
19/82

NOTE

  • 이번 sprints의 개념 설명, 실습은 캐글의 Prediction of H1N1 vaccination을 주로 이용하였다.
  • 백신 접종 여부를 예측하는 분류(Classification) 문제이다.

Decision Trees

Key words

Decision Trees, Gini Impurity, Entrophy, Information Grain, Pipeline, feature importance

Details

개념

  • 분류 문제에서는 모델링하기 전에 항상 타겟 클래스의 범주 확인을 꼭 먼저 하자!! 어떤 분포로 존재하는지, 심각한 데이터 불균형 문제는 없는지 체크하자.
  • high cardinality
    • 너무 많은 범주를 가진 카테고리 특성(피쳐)를 말함. (쉽게 distinct가 많다고 생각하자. 만약 이런 특성까지 원핫인코딩을 하면, 그만큼 차원이 상당히 많아지는 것이기 때문에 모델의 복잡도를 높여 성능이 떨어질 수 있다)
  • pipeline
    • from sklearn.pipeline import make_pipeline 사이킷런에서 제공해준다.
    • 모델링을 하다보면, SimpleImputer, OneHotEncoding, StandarScaler, modeling 등 다양한 작업을 훈련, 검증, 테스트 데이터에 해야하는데, 이 파이프라인 기능을 이용하면 코드 중복을 피하고 간결하게 작성할 수 있게 된다.
    • 데이터 누수(테스트 데이터로 훈련을 한다거나..)를 막는데도 도움이 된다고 한다. 이에 대해선 공감한다. 실습하면서 훈련, 검증 데이터를 엔지니어링 하기 위해 코드를 길게 적다보면 가끔 데이터셋 입력을 실수하겠다는 생각이 들었기 때문이다.
    • pipe.named_steps를 통해 각 스텝별로도 접근이 가능하다. 파이프라인 내의 특정 기능만을 뽑아오거나, coefficient등 특정 정보를 뽑기 위해서 활용하면 된다.
    • 유용한 기능이니 기억해두자!
pipe = make_pipeline(
    OneHotEncoder(), 
    SimpleImputer(), 
    StandardScaler(), 
    LogisticRegression(n_jobs=-1) #참고로 n_jobs=-1은 내 컴퓨터 환경에서 가용한 리소스를 모두 사용하겠다는 뜻이라고 한다.
)
pipe.fit(X_train, y_train)

print('검증세트 정확도', pipe.score(X_val, y_val))

y_pred = pipe.predict(X_test)
  • 결정트리 모델!
    • 결정트리 모델은 특성들을 기준으로 샘플을 분류해 나간다. '마치 스무고개를 하는 것과 같이 특성들의 수치를 가지고 질문을 통해 정답 클래스를 찾아가는 과정으로 보면 된다.'
    • Root Node, Internal Node, Leaf(external, terminal) Node가 있다. 이를 연결하는 선은 Edge라고 한다.
    • 결정트리는 분류와 회귀 문제 모두 적용 가능하다.
    • 시각화를 통해 결정트리 구조를 볼 수 있기 때문에 해석하기 용이한 것이 장점이라고 한다.
    • 단점으로는 아무래도 특성 하나하나를 고려하기 때문에, 훈련 데이터에 과적합될 가능성이 커진다는 것이다. 이 모델을 쓸 때는 과적합 문제가 가장 큰 이슈가 될 것 같다. 외삽도 어렵다.
      • 근데 이걸 바꿔말하면, 선형 회귀 모델에서는 다루기 힘들었던 비선형, 비단조 모델 등에 적용하기 용이하다는 말도 된다.
      • 또한 특성을 하나씩 보기 때문에 특성 상호작용이 있는 경우에도 문제 없이 적용할 수 있다. 선형회귀 모델에서는 다중공선성 문제를 해소하는게 매우 중요한데, 트리모델에서는 이 점에서는 좀 더 연구자를 편하게 해줄 수 있을 것 같다. 특정 간 동일한 환경으로 두어 비교하고자 사용하는 standarscaler도 해줄 필요가 없다. (로지스틱 회귀 모델에서는 특성 간의 관계를 가지고 분류를 하지만 결정트리모델은 한 노드에 하나의 피쳐! 기억!)
    • 사이킷런에 DecisionTreeClassifier()가 있어 모델 구축 자체는 어렵지 않다.
      • 과적합을 방지하기 위해 min_samples_split, min_samples_leaf, max_depth 하이퍼 파라미터를 조절할 수 있다.
  • 불순도(Impurity) / Entrophy
    • 여러 범주가 섞여있는 정도를 말한다. (A, B) 클래스만 들어있는 바구니가 있다고 할 때, A, B가 40%:60%가 있다면, 80%:20%가 있을 때보다 불순도가 높다고 말한다.
    • 이 불순도 개념이 왜 중요하냐면, 결정 트리 모델에서는 각 node에 할당할 피쳐를 정하고 아래로 내려가는 것이 이 불순도를 최대한으로 줄여나가는 방향으로 가기 때문이다. (즉, 가장 중요한 피쳐일 수록 가장 상위 node에 위치할 것이다)
    • 만약 부모 노드의 Gini Impurity보다 자식 노드들의 Gini Impurity 가중평균합이 더 커진다면 노드는 분할되지 않고 부모 노트가 leaf node가 된다. (바로 위 맥락에서 확인하면 이해가 될 것이다)
    • Gini Impurity와 Entrophy는 이 불순도 개념에서는 동일하다고 보면 되고, 결정 트리모델에서 디폴트는 Gini Impurity이다. 지니 불순도는 0~0.5 사이의 값을 가지고, 엔트로피는 0~1 사이의 값을 가진다. 엔트로피에 비해 좀 더 빠른 연산이 가능하다고 한다. 좀 더 세밀하게 보고 싶을 때는 엔트로피를 쓰는 것 같은데 아직 실제 활용해본 적은 없어 잘 모르겠다.
    • 만약 한 노드에서 존재하는 모든 클래스가 한 범주에 속한다면 그 노트의 엔트로피/지니불순도는 0이다.
    • Information Gain(정보 획득)은 특정한 특성을 사용하여 분할했을 때 감소되는 엔트로피의 양을 말한다. 정확히는 부모 노트의 엔트로피에서 자식 노드들 엔트로피의 가중평균합을 뺀 것이다. 말이 어려운데, 그냥 불순도를 얼마나 낮추었는지 정도를 얘기한다고 생각해도 될 것 같다.
  • feature importance
    - 선형회귀에서는 피쳐와 타겟의 관계를 회귀 계수(coefficient)를 통해 보았다. 결정트리 모델에서는 이 feature importance(특성 중요도)를 통해 어떤 특성이 가장 중요한지 확인할 수 있다.
    - feature importance는 항상 양수값을 가지며, 중요할 수록 얼마나 일찍, 자주 분기하는데 사용되는지 알 수 있다.
    - 사이킷런에서는 feature_importances_를 통해 중요도를 확인할 수 있다.

실습 - 결정 트리 모델을 사용하여 위 캐글 대회에 참여하기!!

과정

  • 데이터 불러오기
  • 훈련 데이터 > 훈련, 검증 데이터로 나누기
    • 사이킷런의 train_test_split 함수의 파라미터 중 stratify에 대해서 제대로 공부했다! 해당 파라미터는 지정한 클래스의 분포를 두 데이터로 나눌 때 유사하게 맞춰주는 역할을 한다. 분류 문제에서는 모델의 성능에 있어 매우 매우 중요한 파라미터라고 한다. 이걸 설정하지 않으면 데이터 불균형의 문제가 발생할 수 있으니 꼭 기억하자!
  • 기준 모델 확인 (타겟 클래스의 분포 확인)
  • profiling (데이터셋 특성 및 처리해야할 부분 파악)
  • 데이터 중복 확인
    • duplicates()에 대해서 제대로 공부했다. 해당 함수는 행의 중복 여부를 불린 형태로 반환하는데, 만약 1,3행이 같다면 3행을 True로 반환한다. keep parameter를 통해 조절할 수도 있다. (첫 행을 제외하고 모두 True로 반환할지, 마지막 행을 제외하고 모두 True로 반환할지)
    • train_data.T.duplicated() 이렇게 transpose해서는 행이 아닌 열(피쳐)간 중복되는 것이 있는지도 체크할 수 있으니 참고하자!
    • 중복 데이터는 모델의 성능을 떨어뜨릴 수 있는 주요한 문제라고 하니 항상 잊지말고 체크하기!!
  • feature engineering
    • 함수를 작성해서 불필요한 특성을 제거하는 등의 작업을 하는건데, 여기서 연구자의 아이디어가 많이 들어갈 수 있다고 한다.
    • 나는 high cardinality인 특성을 제거하는 것만 우선 해주었다. 나머지는 잘 모르...겠...었다..
  • 데이터 구분 (X_train, y_train, X_val, y_val)
  • 결정트리 모델 적용 (f1_score 통해 평가)
# Decision Tree 모델링
from sklearn.pipeline import make_pipeline
from category_encoders import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.tree import DecisionTreeClassifier 
from sklearn.metrics import f1_score

pipe = make_pipeline(
    OneHotEncoder(use_cat_names = True),
    SimpleImputer(), #default인 평균으로 대체
    DecisionTreeClassifier(max_depth = 15) #max_depth는 줄이고 늘리며 f1_score 보고 임의로 조정해봄
)
pipe.fit(X_train, y_train) #학습

y_train_pred = pipe.predict(X_train)
y_val_pred = pipe.predict(X_val) #예측값 생성

f1_train = f1_score(y_train, y_train_pred)
f1_val = f1_score(y_val, y_val_pred) #예측값과 실제값의 비교를 통한 score 산출

f1_train, f1_val
  • 특성 중요도 그래프 그려보기
    • 어려웠다. 좀 더 공부가 필요할 것 같다.
  • test data에 대한 예측 데이터 만들어서 캐글 제출하기.

트리모델은 부트캠프 하기 전부터 흥미롭게 봤던 건데 생각보다 개념이 어려워 당황했지만..! 다행히 파이썬에 기능이 잘 구현되어 있어서 모델 적용 자체는 괜찮았다. 오히려 EDA와 특성공학쪽이 훨씬 감을 잡기가 어려웠다. 파이썬에 기능있다고 원리 공부 소홀히할 생각 말고, 모델에 적용되는 원리에 대한 공부도 해야한다!!

profile
B2B SaaS 회사에서 Data Analyst로 일하고 있습니다.

0개의 댓글