ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [분류] 앙상블
    머신러닝 & 딥러닝 2021. 10. 14. 21:43

    앙상블 Learning

    • 여러개의 분류기를 생성하여 그 예측을 결합

    앙상블 학습 유형 : Voting, Bagging, Boosting, Stacking 등Voting Classifier

    • 여러 개의 분류기가 투표를 통해 최종 예측 결과를 결정하는 방식
    • 서로 다른 알고리즘을 가진 분류기를 결합

    Hard Voting

    • 다수결 원칙과 비슷

    Soft Voting

    • 분류기들의 레이블 값 결정 확률을 모두 더하고 이를 평균해서 이들 중 확률이 가장 높은 레이블 값을 최종 보팅 결과값으로 선정
    • 일반적으로 하드 보팅보다 예측 성능이 더 좋다.

     

    import pandas as pd
    
    from sklearn.ensemble import VotingClassifier
    from sklearn.linear_model import LogisticRegression
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score
    
    cancer = load_breast_cancer()
    
    data_df = pd.DataFrame(cancer.data, columns=cancer.feature_names)
    data_df.head(3)

     

    # 개별 모델은 로지스틱 회귀와 KNN 임. 
    lr_clf = LogisticRegression()
    knn_clf = KNeighborsClassifier(n_neighbors=8)
    
    # 개별 모델을 소프트 보팅 기반의 앙상블 모델로 구현한 분류기 
    vo_clf = VotingClassifier( estimators=[('LR',lr_clf),('KNN',knn_clf)] , voting='soft' )
    
    X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, 
                                                        test_size=0.2 , random_state= 156)
    
    # VotingClassifier 학습/예측/평가. 
    vo_clf.fit(X_train , y_train)
    pred = vo_clf.predict(X_test)
    print('Voting 분류기 정확도: {0:.4f}'.format(accuracy_score(y_test , pred)))
    
    # 개별 모델의 학습/예측/평가.
    classifiers = [lr_clf, knn_clf]
    for classifier in classifiers:
        classifier.fit(X_train , y_train)
        pred = classifier.predict(X_test)
        class_name= classifier.__class__.__name__
        print('{0} 정확도: {1:.4f}'.format(class_name, accuracy_score(y_test , pred)))

    Voting 분류기 정확도: 0.9474
    LogisticRegression 정확도: 0.9386
    KNeighborsClassifier 정확도: 0.9386

     

    1.2  Bagging

    • 여러 개의 분류기가 투표를 통해 최종 예측 결과를 결정하는 방식
    • 모두 같은 유형의 알고리즘 기반이지만, 데이터 샘플링을 서로 다르게 가져가면서 학습을 수행해 보팅을 수행.
    • 대표적인 배깅 방식이 랜덤 포레스트 알고리즘
    • 개별 classifier에게 데이터를 샘플링해서 추출하는 방식을 부트스트래핑(Bootstrapping) 분할 방식이라 한다.
    • 개별 분류기가 부트스트래핑 방식으로 샘플링된 데이터 세트에 대해서 학습을 통해 개별적인 예측을 수행한 결과를 보팅을 통해서 최종 예측 결과를 선정하는 방식이 배깅 앙상블 방식.
    • 데이터 중복 허용.
    import pandas as pd
    
    def get_new_feature_name_df(old_feature_name_df):
        feature_dup_df = pd.DataFrame(data=old_feature_name_df.groupby('column_name').cumcount(), columns=['dup_cnt'])
        feature_dup_df = feature_dup_df.reset_index()
        new_feature_name_df = pd.merge(old_feature_name_df.reset_index(), feature_dup_df, how='outer')
        new_feature_name_df['column_name'] = new_feature_name_df[['column_name', 'dup_cnt']].apply(lambda x : x[0]+'_'+str(x[1]) 
                                                                                               if x[1] >0 else x[0] ,  axis=1)
        new_feature_name_df = new_feature_name_df.drop(['index'], axis=1)
        return new_feature_name_df
    import pandas as pd
    
    def get_human_dataset( ):
        
        # 각 데이터 파일들은 공백으로 분리되어 있으므로 read_csv에서 공백 문자를 sep으로 할당.
        feature_name_df = pd.read_csv('../human_activity/features.txt',sep='\s+',
                            header=None,names=['column_index','column_name'])
        
        # 중복된 feature명을 새롭게 수정하는 get_new_feature_name_df()를 이용하여 새로운 feature명 DataFrame생성. 
        new_feature_name_df = get_new_feature_name_df(feature_name_df)
        
        # DataFrame에 피처명을 컬럼으로 부여하기 위해 리스트 객체로 다시 변환
        feature_name = new_feature_name_df.iloc[:, 1].values.tolist()
        
        # 학습 피처 데이터 셋과 테스트 피처 데이터을 DataFrame으로 로딩. 컬럼명은 feature_name 적용
        X_train = pd.read_csv('../human_activity/train/X_train.txt',sep='\s+', names=feature_name )
        X_test = pd.read_csv('../human_activity/test/X_test.txt',sep='\s+', names=feature_name)
        
        # 학습 레이블과 테스트 레이블 데이터을 DataFrame으로 로딩하고 컬럼명은 action으로 부여
        y_train = pd.read_csv('../human_activity/train/y_train.txt',sep='\s+',header=None,names=['action'])
        y_test = pd.read_csv('../human_activity/test/y_test.txt',sep='\s+',header=None,names=['action'])
        
        # 로드된 학습/테스트용 DataFrame을 모두 반환 
        return X_train, X_test, y_train, y_test
    
    
    X_train, X_test, y_train, y_test = get_human_dataset()

     

    1.2.1  학습/테스트 데이터로 분리하고 랜덤 포레스트로 학습/예측/평가

    from sklearn.ensemble import RandomForestClassifier
    from sklearn.metrics import accuracy_score
    import pandas as pd
    import warnings
    warnings.filterwarnings('ignore')
    
    # 결정 트리에서 사용한 get_human_dataset( )을 이용해 학습/테스트용 DataFrame 반환
    X_train, X_test, y_train, y_test = get_human_dataset()
    
    # 랜덤 포레스트 학습 및 별도의 테스트 셋으로 예측 성능 평가
    rf_clf = RandomForestClassifier(random_state=0)
    rf_clf.fit(X_train , y_train)
    pred = rf_clf.predict(X_test)
    accuracy = accuracy_score(y_test , pred)
    print('랜덤 포레스트 정확도: {0:.4f}'.format(accuracy))

    랜덤 포레스트 정확도: 0.9253

     

    1.2.2  GridSearchCV 로 교차검증 및 하이퍼 파라미터 튜닝

    from sklearn.model_selection import GridSearchCV
    
    params = {
        'n_estimators':[100],
        'max_depth' : [6, 8, 10, 12], 
        'min_samples_leaf' : [8, 12, 18 ],
        'min_samples_split' : [8, 16, 20]
    }
    # RandomForestClassifier 객체 생성 후 GridSearchCV 수행
    rf_clf = RandomForestClassifier(random_state=0, n_jobs=-1)
    grid_cv = GridSearchCV(rf_clf , param_grid=params , cv=2, n_jobs=-1 )
    grid_cv.fit(X_train , y_train)
    
    print('최적 하이퍼 파라미터:\n', grid_cv.best_params_)
    print('최고 예측 정확도: {0:.4f}'.format(grid_cv.best_score_))

    최적 하이퍼 파라미터: {'max_depth': 10, 'min_samples_leaf': 8, 'min_samples_split': 8, 'n_estimators': 100}
    최고 예측 정확도: 0.9180

     

    1.2.3  튜닝된 하이퍼 파라미터로 재 학습 및 예측/평가

    rf_clf1 = RandomForestClassifier(n_estimators=300, max_depth=10, min_samples_leaf=8, \
                                     min_samples_split=8, random_state=0)
    rf_clf1.fit(X_train , y_train)
    pred = rf_clf1.predict(X_test)
    print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test , pred)))

    예측 정확도: 0.9165

     

    1.2.4  개별 feature들의 중요도 시각화

    import matplotlib.pyplot as plt
    import seaborn as sns
    %matplotlib inline
    
    ftr_importances_values = rf_clf1.feature_importances_
    ftr_importances = pd.Series(ftr_importances_values,index=X_train.columns  )
    ftr_top20 = ftr_importances.sort_values(ascending=False)[:20]
    
    plt.figure(figsize=(8,6))
    plt.title('Feature importances Top 20')
    sns.barplot(x=ftr_top20 , y = ftr_top20.index)
    plt.show()

     

    1.3  Boosting

    • 대표적인 구현은 AdaBoost, 그래디언트 부스트, XGBoost, LightGBM
    • 약한 학습기를 순차적으로 학습-예측
    • 앞에서 학습한 분류기가 예측이 틀린 데이터에 대해서는 올바르게 예측할 수 있도록 다음 분류기에게는 가중치(weight)를 부여하면서 학습과 예측 진행.

    1.3.1  GBM (Gradient Boost Machine)

    • 오류 값 = 실제 값 - 예측 값
    • 반복 수행을 통해 오류를 최소화 할 수 있게 한다.
    • 에이다부스트와 유사하나 가중치 업데이트를 경사 하강법(Gradient Descent)를 이용

    1.3.2  사이킷런 GBM

    • GradientBoostingClassifier 클래스 제공
    • learning_rate : GBM이 학습을 진행 할 때마다 적용하는 학습률.
    • subsample : 학습에 사용하는 데이터의 샘플링 비율.



    GBM(Gradient Boosting Machine)

    from sklearn.ensemble import GradientBoostingClassifier
    import time
    import warnings
    warnings.filterwarnings('ignore')
    
    X_train, X_test, y_train, y_test = get_human_dataset()
    
    # GBM 수행 시간 측정을 위함. 시작 시간 설정.
    start_time = time.time()
    
    gb_clf = GradientBoostingClassifier(random_state=0)
    gb_clf.fit(X_train , y_train)
    gb_pred = gb_clf.predict(X_test)
    gb_accuracy = accuracy_score(y_test, gb_pred)
    
    print('GBM 정확도: {0:.4f}'.format(gb_accuracy))
    print("GBM 수행 시간: {0:.1f} 초 ".format(time.time() - start_time))

    GBM 정확도: 0.9393

    GBM 수행 시간: 532.8 초

    from sklearn.model_selection import GridSearchCV
    
    params = {
        'n_estimators':[100, 500],
        'learning_rate' : [ 0.05, 0.1]
    }
    grid_cv = GridSearchCV(gb_clf , param_grid=params , cv=2 ,verbose=1)
    grid_cv.fit(X_train , y_train)
    print('최적 하이퍼 파라미터:\n', grid_cv.best_params_)
    print('최고 예측 정확도: {0:.4f}'.format(grid_cv.best_score_))
    scores_df = pd.DataFrame(grid_cv.cv_results_)
    scores_df[['params', 'mean_test_score', 'rank_test_score',
    'split0_test_score', 'split1_test_score']]

    # GridSearchCV를 이용하여 최적으로 학습된 estimator로 predict 수행. 
    gb_pred = grid_cv.best_estimator_.predict(X_test)
    gb_accuracy = accuracy_score(y_test, gb_pred)
    print('GBM 정확도: {0:.4f}'.format(gb_accuracy))

    GBM 정확도: 0.9196

     

    [파이썬 머신러닝 완벽 가이드] 교재를 바탕으로 쓴 블로그입니다. 

    댓글