Ensemble 학습의 Bagging 의 대표적인 방식

앙상블이랑 여러개의 알고리즘을 사용하여, 그 예측을 결정함으로써 보다 정확한 예측을 도출하는 기법.

기존의 Decision Tree에서 그 트리가 엄청많아져서, 그것들의 최종 값의 비율로 계산하자!

각각 부트스트랩으로 만들어진 데이터셋으로 학습하게되는데, 이를 Bagging (Bootstrap AGGregatING) 이라고 한다.

오리지널 데이터에서 복원추출하는데, 샘플을 뽑고, 다시 원본에서 샘플을 뽑는다. (중복될 수 있다는것)
원본 데이터셋에서 복원추출하는 것을 Bootstrap Sampling이라 한다.
그렇게 samples들을 뽑아서 원본과 같은 수의 sample을 구성하면 그게 부트스트랩샘플을 하나 만들었다고 한다.
각각의 부트스트랩 샘플의 Training set 에서 뽑히지 않은 샘플들을 test set으로 분류하고 이를 OOB Sample이라고 한다.
→ 100 개 데이터 중 70개로 트레인하고, 나머지 30개로 validation을 매 트리 생성시마다 한다고 보면 됨.

앙상블 기법은 한 종류의 데이터로 여러 학습모델을 만들어, 그 모델들의 예측결과를 다수결이나 펴균을 내어 예측하는 방법을 말한다.

랜덤포레스트는 Decision Tree를 기본모델로 사용한다.

부트스트랩 세트의 크기가 n일 때, 한번의 추출에서 어느 한 샘플이 추출되지 않을 확률은 ${n-1} \over n$ 이다. 
그것을 n번 반복였을 때에도 그 샘플이 추출되지 않았을 확률은 $ ({{n-1}\over n})^2$ 이다.
이게 이제 무한히 커지면 어느 한 점으로 수렴하게 되는데.

결과적으로 데이터가 충분할 때 한 부트스트랩 세트는 63.2%의 샘플을 갖고, 
여기에 속하지 않은 36.8% 의 샘플이 Out-of_Bag 샘플이며, 이것이 검증에 사용된다.

트리모델에서는 One-hot Encoding보다 Ordinal Encoding이 좀더 성능이 좋을 때가 많다.
원핫으로 피쳐가 추가되었을 때, 트리에서는 상위노드에서 중요한 피처가 사용되므로, 하나의 피쳐가 여러개의 피쳐로 쪼개진 One-Hot에서 범주 종류가 많은 (High Cardinality) 피쳐였을 경우 상위노드에서 선택될 가능성이 적어진다.

  • n_estimators = 트리의 갯수 | number of trees in the foreset
  • max_features = 노드들 구분할 때 고려할 최대 피쳐수 | max number of features considered for splitting a node
  • max_depth = 각 트리의 최대 깊이 | max number of levels in each decision tree
  • min_samples_split = 최소 분할 샘플 갯수 | min number of data points placed in a node before the node is split
  • min_samples_leaf = 최소 잎 노드 데이터 수 | min number of data points allowed in a leaf node
  • bootstrap = 복원 추출 | method for sampling data points (with or without replacement)

랜덤 포레스트의 Pseudo Code

S는 트레이닝셋, Feature 는 F, 랜덤포레스트 안의 트리는 B 라고 한다.
H를 초기화하고, 
1부터 B까지 (트리들을 순회하면서),
$S^(i)$ 에 S로 부터 만든 부트스트랩 샘플을 넣고, 
$h_i$ 에 트리를 학습시키고(트리의 학습은, 각각의 노드에서 feature의 subset을 최적으로 쪼개면서 학습시킨다. )
이후, 학습된 트리들 하나하나를 H에 합친 후, 최종 H를 리턴. 

from sklearn.model_selection import train_test_split

train, val = train_test_split(train, train_size=0.8, test_size=0.2,
                              stratify=train[target], random_state=2)
                              
##############################################                              
from category_encoders import OrdinalEncoder
from sklearn.pipeline import make_pipeline

pipe_ordinal_simple=make_pipeline(verbose=0,
    OrdinalEncoder(verbose=0),
    SimpleImputer(),
    RandomForestClassifier(n_jobs=-1, random_state=10, oob_score=True)
)

pipe_ordinal_simple.fit(X_train,y_train)
pipe_ordinal_simple.score(X_val,y_val) #0.8258806784485826

ㅇ 이렇게 파이프라인속에 넣어서 사용할 수도 있다. 
X_train으로 fit(학습)시키고, X_val로 분리해놓은 데이터를 통하여 점수를 매겨보는 등의 작업을 하면된다. 

 

하이퍼파라미터 튜닝

  • n_estimators = 트리의 갯수 | number of trees in the foreset
  • max_features = 노드들 구분할 때 고려할 최대 피쳐수 | max number of features considered for splitting a node
  • max_depth = 각 트리의 최대 깊이 | max number of levels in each decision tree
  • min_samples_split = 최소 분할 샘플 갯수 | min number of data points placed in a node before the node is split
  • min_samples_leaf = 최소 잎 노드 데이터 수 | min number of data points allowed in a leaf node
  • bootstrap = 복원 추출 | method for sampling data points (with or without replacement)
  • class_weight =  sample의 라벨 비율 ->  기존의 분류문제에서 라벨비율이 비슷하지 않으면, 좋지 않은 학습결과를 가져올 수 있는데, 이를 처리해줌.

class_weight 설정

어떠한경우 target 의 class 비율이 다를 수 있다. 이는 모델 학습에 악영향을 끼치는데, 이 부분에 대하여 RandomForest에서는 class_weight라는 파라미터를 준다. 

from sklearn.utils.class_weight import compute_class_weight
print(y_train.unique(),'\n',y_train.value_counts())
compute_class_weight(class_weight='balanced', classes = y_train.unique(), y=y_train)
# [0 1] 
# 0    29269
# 1     3681
# Name: y, dtype: int64
# array([0.56288223, 4.47568595])
## _____________________ ## 
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(n_estimators=250, class_weight={1:0.56288223 , 0:4.47568595})
rfc.fit(X_train, y_train)
rfcpred = rfc.predict(X_val)

print(confusion_matrix(y_val, rfcpred))
print('Accuracy Score : ',accuracy_score(y_val, rfcpred))
print('f1 Score : ',f1_score(y_val, rfcpred))
print('\nRandomForest Regression Matrix\n' , classification_report(y_val,rfcpred))

이를 통하여 불균형한 데이터 셋에서 Upsampling과 Downsampling하지 않고도 주어진 데이터를 최선으로 활용하여 학습을 진행할 수 있다. 

 

Max_depth 튜닝

def pipe_ordinal_simple_elbow(howmany,X_train, y_train, X_val, y_val):
    trainAccuracy=[]
    valAccuracy=[]
    for depth in range(1,howmany):
        pipe_ordinal_simple=make_pipeline(
            OrdinalEncoder(verbose=0),
            SimpleImputer(),
            RandomForestClassifier(max_depth=depth,n_jobs=-1, random_state=10, oob_score=True)
        )
        pipe_ordinal_simple.fit(X_train,y_train)
        trainAccuracy.append(pipe_ordinal_simple.score(X_train,y_train))
        valAccuracy.append(pipe_ordinal_simple.score(X_val,y_val))
    return trainAccuracy, valAccuracy
ta_msl , tv_msl = pipe_ordinal_simple_elbow(howmany=20 , 
                                             X_train=X_train,
                                             y_train=y_train, 
                                             X_val=X_val, 
                                             y_val=y_val)
                                             
pd.DataFrame({'msl_training': ta_msl, 'msl_val':tv_msl}, index=range(1,20)).plot(figsize=(10,8))
plt.grid()

 

depth 가 7~8을 넘어가는 부분부터 training과 validation의 accuracy score가 확연히 달라진다. 
깊어질수록 training은 정확도가 높아지는반면, val의 정확도는 거의 변하지않는다. 이는 과적합되는 부분이라고 봐도 될것이다.

n_estimator

n_estimators = 트리의 갯수 | number of trees in the foreset
한마디로 투표용지의 개수가 얼마나 많아지는가? 라고 생각하면 된다. 

def pipe_ordinal_simple_elbow_estimators(howmany,X_train, y_train, X_val, y_val):
    trainAccuracy=[]
    valAccuracy=[]
    for depth in range(10,howmany, 20):
        pipe_ordinal_simple=make_pipeline(
            OrdinalEncoder(verbose=0),
            SimpleImputer(),
            RandomForestClassifier(n_estimators=depth,n_jobs=-1, random_state=10, oob_score=True)
        )
        pipe_ordinal_simple.fit(X_train,y_train)
        trainAccuracy.append(pipe_ordinal_simple.score(X_train,y_train))
        valAccuracy.append(pipe_ordinal_simple.score(X_val,y_val))
    return trainAccuracy, valAccuracy
ta_msl , tv_msl = pipe_ordinal_simple_elbow_estimators(howmany=200 , 
                                             X_train=X_train,
                                             y_train=y_train, 
                                             X_val=X_val, 
                                             y_val=y_val) 
                                             
pd.DataFrame({'msl_training': ta_msl, 'msl_val':tv_msl}, index=range(10,200,20)).plot(figsize=(10,8))
plt.grid()

시작을 10부터 잡아서 그런지, 거의 변화가 너무 적다. 하지만 확실하게 1부터 시작한다면 증가하는 폭을 볼 수 있을것이다.

 

GridSearchCV 를 통한 하이퍼파라미터 튜닝

from sklearn.model_selection import GridSearchCV

params = { 'randomforestclassifier__n_estimators' : [50, 100, 150],
           'randomforestclassifier__max_depth' : [6, 9, 12],
           'randomforestclassifier__min_samples_leaf' : [8, 12],
           'randomforestclassifier__min_samples_split' : [8, 16]
            }
pipe_ordinal_simple=make_pipeline(
            OrdinalEncoder(verbose=0),
            SimpleImputer(),
            RandomForestClassifier(n_jobs=-1, random_state=10, oob_score=True)
        )
grid=GridSearchCV(pipe_ordinal_simple , param_grid=params , cv=5, verbose=0)
grid.fit(X_train,y_train)
grid.best_estimator_
Pipeline(steps=[('ordinalencoder',
                 OrdinalEncoder(cols=['opinion_h1n1_vacc_effective',
                                      'opinion_h1n1_risk',
                                      'opinion_h1n1_sick_from_vacc',
                                      'opinion_seas_vacc_effective',
                                      'opinion_seas_risk',
                                      'opinion_seas_sick_from_vacc', 'agegrp',
                                      'employment_status', 'census_msa',
                                      'state'],
                                mapping=[{'col': 'opinion_h1n1_vacc_effective',
                                          'data_type': dtype('O'),
                                          'mapping': Somew...
TENNESSEE              39
FLORIDA                40
NEW HAMPSHIRE          41
IDAHO                  42
MAINE                  43
ALASKA                 44
WISCONSIN              45
OKLAHOMA               46
MASSACHUSETTS          47
NORTH DAKOTA           48
WASHINGTON             49
NEBRASKA               50
HAWAII                 51
NaN                    -2
dtype: int64}])),
                ('simpleimputer', SimpleImputer()),
                ('randomforestclassifier',
                 RandomForestClassifier(max_depth=12, min_samples_leaf=12,
                                        min_samples_split=8, n_estimators=150,
                                        n_jobs=-1, oob_score=True,
                                        random_state=10))])

이러한 출력을 볼 수 있다. 

이제 이 파라미터들의 상태를 시각화해본다

cols='param_randomforestclassifier__max_depth param_randomforestclassifier__min_samples_leaf	param_randomforestclassifier__min_samples_split	param_randomforestclassifier__n_estimators mean_test_score'.split()
griddf=pd.DataFrame(grid.cv_results_)
fig,axs=plt.subplots(2,2, figsize=(10,10))
sns.pointplot(ax=axs[0][0], data=griddf, x=cols[0],y=cols[-1])
sns.pointplot(ax=axs[0][1], data=griddf, x=cols[1],y=cols[-1])
sns.pointplot(ax=axs[1][0], data=griddf, x=cols[2],y=cols[-1])
sns.pointplot(ax=axs[1][1], data=griddf, x=cols[3],y=cols[-1])

max_depth의 변화에 가장 크게 증가하였으며, 그외에는 오히려 조금 떨어진 경우가 많았다. 

Feature Importance

plt.figure(figsize=(4,8), dpi=110)
sns.barplot(data=
            pd.DataFrame(grid.best_estimator_['randomforestclassifier'].feature_importances_,
                         index=X_train.columns, columns=['feature_importances_']).reset_index().sort_values('feature_importances_',ascending=False)
                         , x='feature_importances_', y='index')

 

'Machine Learning > Tree Based Models' 카테고리의 다른 글

Decision Tree (결정트리)  (0) 2021.02.10

결정트리모델은 특성들을 기준으로 샘플을 분류해 나가는데, 마치 Tree model처럼 뻗어나간다고해서 Decision Tree라는 이름을 갖는다.

결정트리는 학습 결과로 IF-THEN 형태의 규칙이 만들어진다.

결정트리는 퍼셉트론이나 로지스틱 회귀와 달리 선형 분리 불가능한 데이터도 분류할 수 있으나, 선형분리 가능한 문제는 잘 풀지 못한다. 또한 데이터를 조건 분기로 나눠가는 특성상, 트리가 깊어질수록 학습에 사용되는 데이터 수가 적어져 과적합을 일으키기 쉽다.

결정 트리는 학습 데이터로부터 조건식을 만들고, 예측할 때는 트리의 루트(최상위조건)부터 순서대로 조건분기를 타면서 리프에 도착하면 예측결과를 내는 알고리즘이다.

불순도(Impurity)를 기준으로 가능한 한 같은 클래스끼리 모이도록 조건 분기를 학습한다.

구체적으로는 정보획득(Information Gain)이나 지니게수(Gini Coefficient)등의 값을 불순도로 사용해, 그 값이 낮아지도록 데이터를 분할한다.

이후 결정트리가 응용되어 랜덤포레스트와 경사부스팅결정트리가 생겨났다.

결정트리의 각 노드는 뿌리, 중간, 말단 노드로 나뉠 수 있다.

지니불순도

※ 지니계수 : 경제학에서 불평등지수를 나타낼 때 사용하는 것으로 0일 때 완전 평등, 1일 때 완전 불평등을 의미합니다.

머신러닝에서는 데이터가 다양한 값을 가질수록 평등하며 특정 값으로 쏠릴 때 불평등한 값이 됩니다. 즉, 다양성이 낮을수록 균일도가 높다는 의미로 1로 갈수록 균일도가 높아 지니계수가 높은 속성을 기준으로 분할

임의의 새로운 변수가 데이터셋으로부터 클래스 라벨의 분포를 따라 무작위로 분류된 경우, 임의 변수의 새로운 인스턴스의 잘못된 분류 가능성에 대한 측정치.
분류가 잘 되었는지 판단할 수 있는 척도이다.
$G_i = {1 - \Sigma_{k=1}^n{p_ik^2} }$

$I_G(p) = \Sigma_{i=1}^J{p_i ( 1-p_i) } = 1 - \Sigma_{i=1}^J{p_i^2} $
정보획득은 특정한 특성을 사용해 분할했을 떄 엔트로피의 감소량을 뜻한다.

여기서 불순도(impurity) 라는 개념은 여러 범주가 섞여 있는 정도를 이야기 한다.
예를들어 A, B 두 클래스가 혼합된 데이터가 있을 때 (A, B) 비율이 (45%, 55%)인 샘플(두 범주 수가 비슷)은 불순도가 높은 것이며
(80%, 20%)인 샘플이 있다면 상대적으로 위의 상태보다 불순도가 낮은 것 입니다. (순수도(purity)는 높음)

지니 이득 = 뿌리 지니값 - 좌측 잎 비율 좌측 지니값 - 우측 잎 비율 우측 지니값

엔트로피

${\displaystyle \mathrm {H} (T)=\operatorname {I} _{E}\left(p_{1},p_{2},...,p_{J}\right)=-\sum _{i=1}^{J}{p_{i}\log _{2}p_{i}}}$

불순도를 측정하는 지표로서, 정보량의 기댓값.

$Entropy(S) = \Sigma_{i=1}^c{p_i * I(x_i)}$

S : 이미 발생한 사건의 모음 , c: 사건의 개수

정보량이란? :: 어떤 사건이 갖고있는 정보의 양을 의미하며, $I(x) = \log_2{1\over{p(x)}}$ 이다.

여기서 $p(x) : 사건이 발생할 확률$

사건 x가 발생할 확률을 x축, 정보량을 y축으로 그래프를 그리면

사건 x가 발생할 확률이 증가할 수록 정보량은 0에 수렴 → 자주 발생하는 사건일수록 정보량이 떨어진다!

순도 100% (한 종류의 class만 있는경우) 의 경우에는 Entropy가 0이고, 두 클래스가 정확히 반반 섞여있을 때 Entropy가 가장 높다.

___

결정트리의 특성

  • 학습한 모델을 사람이 해석하기 쉽다.
  • 입력 데이터를 정규화 할 필요가 없다.
  • 범주형 변수나 데이터의 누락값 (NaN)이 있어도 용인된다.
  • 특정 조건에서 과적합을 일으키기 쉽다.
  • 비선형 문제에는 적용할 수 있지만, 선형 분리 문제는 잘 풀지 못한다.
  • 데이터의 분포가 특정 클래스에 쏠려있으면 잘 풀지 못한다.
  • 데이터의 작은 변화에도 결과가 크게 바뀌기 쉽다.
  • 예측 성능은 보통이다.
  • 배치 학습으로만 학습할 수 있다.
Parameter Describe
min_samples_split 노드를 분할하기 위한 최소한의 샘플 데이터수 → 과적합을 제어하는데 사용-
  Default = 2 → 작게 설정할 수록 분할 노드가 많아져 과적합 가능성 증가
min_samples_leaf 리프노드가 되기 위해 필요한 최소한의 샘플 데이터수- min_samples_split과 함께 과적합 제어 용도

  - 불균형 데이터의 경우 특정 클래스의 데이터가 극도로 작을 수 있으므로 작게 설정 필요
max_features 최적의 분할을 위해 고려할 최대 feature 개수- Default = None → 데이터 세트의 모든 피처를 사용
  - int형으로 지정 →피처 갯수 / float형으로 지정 →비중- sqrt 또는 auto : 전체 피처 중 √(피처개수) 만큼 선정
  - log : 전체 피처 중 log2(전체 피처 개수) 만큼 선정
max_depth 트리의 최대 깊이- default = None→ 완벽하게 클래스 값이 결정될 때 까지 분할또는 데이터 개수가 min_samples_split보다 작아질 때까지 분할
  -깊이가 깊어지면 과적합될 수 있으므로 적절히 제어 필요
max_leaf_nodes 리프노드의 최대 개수

Decision Tree의 과적합을 줄이기 위한 파라미터 튜닝

(1) max_depth 를 줄여서 트리의 깊이 제한

(2) min_samples_split 를 높여서 데이터가 분할하는데 필요한 샘플 데이터의 수를 높이기

(3) min_samples_leaf 를 높여서 말단 노드가 되는데 필요한 샘플 데이터의 수를 높이기

(4) max_features를 높여서 분할을 하는데 고려하는 feature의 수 제한

min_samples_leaf 를 높여서 말단 노드가 되는데 필요한 샘플 데이터의 수를 높이기

from category_encoders import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.pipeline import make_pipeline
from sklearn.tree import DecisionTreeClassifier

def pipe_min_sample_leaf_elbow(howmany,X_train,y_train,X_val,y_val):
    trainAccuracy=[]
    valAccuracy=[]
    for leafs in range(1,howmany):
        pipe_msl=make_pipeline(
            OneHotEncoder(),
            SimpleImputer(),
            DecisionTreeClassifier(min_samples_leaf=leafs, random_state=2)
        )
        pipe_msl.fit(X_train,y_train)
        trainAccuracy.append(pipe_msl.score(X_train,y_train))
        valAccuracy.append(pipe_msl.score(X_val,y_val))
    return trainAccuracy, valAccuracy


ta_msl , tv_msl = pipe_min_sample_leaf_elbow(howmany=30 , 
                                             X_train=X_train_oh,
                                             y_train=y_train, 
                                             X_val=X_val_oh, 
                                             y_val=y_val)

pd.DataFrame({'msl_training': ta_msl, 'msl_val':tv_msl}, index=range(1,30)).plot(figsize=(10,8))
plt.grid()

최종 Leaf의 수가 많아질 수록 점점 train데이터의 정확도가 줄어드는 반면, Validation데이터의 정확도는 증가합니다.

하지만 어느정도 한계가 있는듯, 곡선의 기울기가 약 leafs=15부터는 상승하는 정도가 매우 작아집니다.

max_depth 를 줄여서 트리의 깊이 제한

  • 트리의 최대 깊이
  • default = None → 완벽하게 클래스 값이 결정될 때 까지 분할 또는 데이터 개수가 min_samples_split보다 작아질 때까지 분할
  • 깊이가 깊어지면 과적합될 수 있으므로 적절히 제어 필요
def pipe_max_depth_elbow(howmany,X_train,y_train,X_val,y_val):
    trainAccuracy=[]
    valAccuracy=[]
    for depth in range(1,howmany):
        pipe_msl=make_pipeline(
        	OneHotEncoder(),
            SimpleImputer(),
            DecisionTreeClassifier(max_depth=depth, random_state=2)
        )
        pipe_msl.fit(X_train,y_train)
        trainAccuracy.append(pipe_msl.score(X_train,y_train))
        valAccuracy.append(pipe_msl.score(X_val,y_val))
    return trainAccuracy, valAccuracy
    
ta_mxd , tv_mxd = pipe_max_depth_elbow(howmany=20 , 
                                             X_train=X_train_oh,
                                             y_train=y_train, 
                                             X_val=X_val_oh, 
                                             y_val=y_val)

pd.DataFrame({'mxd_training': ta_mxd, 'mxd_val':tv_mxd}, index=range(1,20)).plot(figsize=(10,8))
plt.grid()

 

max_depth 는 트리의 최대 깊이를 나타냅니다.
default 는 None으로 완벽하게 클래스 값이 결정될때까지 or min_samples_split보다 작아질 때 까지 분할합니다.
깊이가 깊어질 수록 과적합될 가능성이 높아집니다. training데이터의 경우 깊이가 깊어질수록 정확도가 한없이 증가하는 모습을 보입니다.
하지만 validation데이터의 경우 깊이가 깊어질 수록 정확도가 떨어지는 모습을 보입니다.
해당 depth에 맞게 training데이터가 학습(fit)된 이후, validation데이터가 해당 트리를 통해 걸러져서 분류된 결과가 depth가 깊어짐에 따라 점점 안맞게 된다는 뜻으로 해석됩니다.

min_samples_split 를 높여서 데이터가 분할하는데 필요한 샘플 데이터의 수를 높이기

def pipe_min_sample_split_elbow(howmany,X_train,y_train,X_val,y_val):
    trainAccuracy=[]
    valAccuracy=[]
    for splits in range(1,howmany):
        pipe_msl=make_pipeline(
        	OneHotEncoder(),
            SimpleImputer(),
            DecisionTreeClassifier(min_samples_split=splits, random_state=2)
        )
        pipe_msl.fit(X_train,y_train)
        trainAccuracy.append(pipe_msl.score(X_train,y_train))
        valAccuracy.append(pipe_msl.score(X_val,y_val))
    return trainAccuracy, valAccuracy
    
ta_mss , tv_mss = pipe_min_sample_leaf_elbow(howmany=20 , 
                                             X_train=X_train_oh,
                                             y_train=y_train, 
                                             X_val=X_val_oh, 
                                             y_val=y_val)
                                             
pd.DataFrame({'mss_training': ta_mss, 'mss_val':tv_mss}, index=range(1,20)).plot(figsize=(10,8))
plt.grid()

min_samples_split : int or float, default=2

The minimum number of samples required to split an internal node: 규칙노드(내부노드)의 분기를 위한 최소 샘플 개수를 지정하는 방식입니다.
기존의 디폴트값은 2로, 어떤 하나와 다른 하나가 나타나는 순간 그 지점에서 분기를 하는반면, 값이 커질수록 다른 n개의 sample이 나타나야 분기를 하는것으로, 분기하는 정도가 조금 더 약해진다고 볼 수 있습니다.

GridSearchCV를 통한 튜닝

from sklearn.model_selection import GridSearchCV
params = {
    'max_depth' : [4, 5, 6, 7, 8, 9, 10],
    'min_samples_split' : range(10,20),
    'min_samples_leaf' : range(5,15)
         }

gridCV = GridSearchCV(DecisionTreeClassifier(random_state=2), 
                      param_grid=params, scoring='accuracy', cv=5, verbose=1)

## OneHotEncoder() 미리 사용

ohe=OneHotEncoder()
X_train_oh = ohe.fit_transfort(X_train)
X_val_oh = ohe.transform(X_val)
X_test_oh = ohe.transform(X_test)

## SimpleImuter() 를 미리 사용
imp_mean=SimpleImputer()
X_train_oh_imputed = imp_mean.fit_transform(X_train_oh)
X_val_oh_imputed = imp_mean.transform(X_val_oh)
X_test_oh_imputed = imp_mean.transform(X_test_oh)

## GridSearchCV사용
gridCV.fit(X_train_oh_imputed , y_train)

print(gridCV.best_score_)
gridCV.best_params_

# 0.8244818005868766
# {'max_depth': 7, 'min_samples_leaf': 14, 'min_samples_split': 10}

GridSearchCV를 사용해서 params의 조합을 통하여 엄청난 연산을 수행 끝에 거의 5분~10분만에 끝났습니다.
최고 스코어는 : 0.8244818005868766
그 때의 조합 : {'max_depth': 7, 'min_samples_leaf': 14, 'min_samples_split': 10}
이 조합이 기존에 Pipeline으로 하던 것에서 최상의 조합이라고 볼 수 있습니다.
(지금까지는.. 아마 나중에 뭔가 다른방법을 알게된다면 시도해보겠습니다.)

from sklearn import tree

gridbest = gridCV.best_estimator_

plt.figure(figsize=(12,12), dpi=200)
tree.plot_tree(gridbest,max_depth=3);

 

각 columns의 중요도 시각화
doctor_recc_h1n1
의사의 권유가 있었다는 feature가 중요성이 높았고, 그 다음 건강보험 유무였는데, 이 두 변수 사이에 작은 상관관계가 있을것으로 추정됩니다. 그 이유는 보험있는사람들이 병원에 좀더 자유롭게 (가격부담없이) 진료받으러 갔을것이며, 또한 보험이 있기에 백신접종 또한 권유를 더 잘받지않았을까? 또한, 세번째 피쳐가 백신이 효과적이라고 생각하는것 네번째가 의료종사자, 다섯번째는 백신위험이 적다는의견입니다.

plt.figure(figsize=(6,10))
pd.Series(gridbest.feature_importances_, X_train_oh.columns).sort_values().tail(15).plot.barh()

 

 

참조:

머신러닝 실무 프로젝트 / 아리아 미치아키 / 한빛미디어

[Chapter 4. 분류] Decision Tree Classifier :: 데이터분석, 머신러닝 정리 노트 (tistory.com)
참조2

(https://injo.tistory.com/15)

'Machine Learning > Tree Based Models' 카테고리의 다른 글

Random Forests 랜덤포레스트  (0) 2021.02.10

+ Recent posts