[머신러닝 기초] 지도학습 - classification (Ensemble, Random Forest)
목차
1. 앙상블 (ensemble)
2. Bagging
- 2-1) Random Foreset
3. Boosting
4. Staking
1. 앙상블(ensemble)
- 여러개의 분류기(classifier)를 생성하고, 그 예측을 결합함으로써 더 정확한 최종 예측을 도출하는 기법
- 어려운 문제를 풀기위해 여러명의 전문가로 구성해 다양한 의견을 수렴하고 결정하는 방법과 유사
1-1) 앙상블 유형
- 보팅 (Voting) : 서로 다른 알고리즘을 가진 분류기를 결합
- 배깅 (Bagging, Bootstrap AGGregatING) : 모두 같은 유형의 알고리즘을 사용하지만, 데이터 샘플링(sampling with replacement, 복원추출)을 서로 다르게 가져가면서 보팅을 수행, RandomForest
- 데이터 샘플링 => 부트스트래핑(Bootstrapping) 분할 방식을 사용
- 부스팅 (Boosting) : 여러개의 분류기가 순차적으로 학습을 수행하되, 앞에서 학습한 분류기가 예측이 틀린 데이터에 대해서는 올바르게 예측할 수 있도록 다음 분류기에게는 가중치(weight)를 부여하면서 학습과 예측을 진행, XGBoost, LightGBM
- 스태킹 (Stacking) : 여러가지 다른 모델의 예측 결괏값을 다시 학습 데이터로 만들어서 다른 모델(메타모델)로 재학습시켜 결과를 예측하는 방법
등등....
1-2) Voting 방식
Voting방식은 Hard Voting, Soft Voting이 있으며, 일반적으로 Soft Voting이 예측성능이 우수하여 더 많이 사용한다.
1-3) 부트스래핑
- 복원추출 샘플링
- 데이터가 중복되어 구성될 수도 있고, 데이터가 아에 포함이 안될 수도(OOB, Out of Bag) 있다.
- 이는 데이터가 갖는 분포를 왜곡시켜주는 효과가 있어 학습을 더 정확하게 할 수 있으며, OOB를 사용하여 데이터 검증을 할 수 있다.
2. Bagging (Bagging, Bootstrap AGGregatING)
- 모두 같은 유형의 알고리즘을 사용
- 데이터 샘플링을 Bootstraping 기법을 사용
- 예측결과를 합침 (Aggregation), 합치는 방법은 다양함
2-1) Random Forest
- Random Forest는
1) Forest : Decision Tree를 여러개의 분류기로 ensemble
2) Random : 변수(feature, variable)를 임의(random)선택함
- Bagging 방식으로 같은 알고리즘으로 여러개의 분류기를 만들어서 보팅으로 최종 결정하는 알고리즘
- bootstraping 방식으로 데이터 샘플링
- 여러개의 결정 트리 분류기가 전체 데이터에서 배깅 방식으로 각자의 데이터를 샘플링해 개별적으로 학습을 수행한 뒤 최종적으로 모든 분류기가 소프트보팅을 통해 예측을 결정
Sklearn API
이를 위해 sklearn에서는 API를 지원한다.
목적 | import | API |
Random Forest | from sklearn.ensemble import RandomForestClassifier | RandomForestClassifier() |
주로 사용하는 parameter는 다음과 같다.
** Decision Tree에서 과적합을 개선하기 위한 파라메터도 똑같이 적용됨
파라메터 | 설명 |
n_estimators | - 결정 트리 개수 - default : 10 ** 많이 설정할 수록 좋은 성능을 기대할 수 있지만 계속 증가시킨다고 무조건 향상되는 것은 아님 |
max_features | - sqrt |
max_depth | ** Decision Tree와 동일 |
min_samples_leaf | |
min_samples_split |
> 참고 : 전체 코드 Link (클릭)
코드에서 보면,
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
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)))
GridSearchCV를 사용하는 경우,
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
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_))
Feature importance를 확인 한다면,
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()
3. Boosting
: 여러개의 분류기가 순차적으로 학습을 수행하되, 앞에서 학습한 분류기가 예측이 틀린사항(ex. 데이터, 잔차)을 다음 분류기에게는 올바르게 예측할 수 있도록 가중치(weight)를 부여하면서 학습과 예측을 진행
1) 아다부스트 (AdaBoost) : 오류 데이터에 가중치를 부여하여, 다음 수행에는 더 많이 샘플링 될 수 있도록(부스팅)함
- 즉, 데이터의 샘플링이 달라짐
2) 그래디언트 부스트 (Gradient Boost) : Gradient Decent + Boosting 을 의미한다.
- 데이터는 그대로 사용하고, residual(잔차, 실제값-예측값)을 최소화하는 방향성을 가진다.
잔차로 학습을 진행하므로, overfitting될 가능성이 높음
overfitting을 막기 위해서 (과적합 규제, Regularization)
1) subsampling : 데이터의 일부만 학습
2) early stopping : 설정한 반복횟수를 끝까지 수행하는 것이 아니라, 검증용 데이터셋의 오류가 높아지기 전에 초기 중단을 시키는 방법
등의 방식을 사용함
다음부터 배울 GBM, XGBoost, LightGBM는 boosting기법을 사용하여 각 알고리즘들의 단점을 보완하면서 발전하였음.
3-1) GBM
Sklearn API
이를 위해 sklearn에서는 API를 지원한다.
목적 | import | API |
GBM | from sklearn.ensemble import GradientBoostingClassifier |
GradientBoostingClassifier() |
코드에서 보면,
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))
GridSearchCV를 사용하는 경우,
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_))
# 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))
3-2) XGBoost
Sklearn API
이를 위해 sklearn에서는 API를 지원한다.
목적 | import | API |
XGBoost | from xgboost import XGBClassifier |
XGBClassifier() |
코드에서 보면,
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score, roc_auc_score
def get_clf_eval(y_test, pred=None, pred_proba=None):
confusion = confusion_matrix( y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)
# ROC-AUC 추가
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
# ROC-AUC print 추가
print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f},\
F1: {3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
######################################################################
# 사이킷런 래퍼 XGBoost 클래스인 XGBClassifier 임포트
from xgboost import XGBClassifier
xgb_wrapper = XGBClassifier(n_estimators=400, learning_rate=0.1, max_depth=3)
xgb_wrapper.fit(X_train, y_train)
w_preds = xgb_wrapper.predict(X_test)
w_pred_proba = xgb_wrapper.predict_proba(X_test)[:, 1]
get_clf_eval(y_test , w_preds, w_pred_proba)
3-3) LightGBM
Sklearn API
이를 위해 sklearn에서는 API를 지원한다.
목적 | import | API |
LightGBM | from lightgbm import LGBMClassifier | LGBMClassifier() |
코드에서 보면,
# LightGBM의 파이썬 패키지인 lightgbm에서 LGBMClassifier 임포트
from lightgbm import LGBMClassifier
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score, roc_auc_score
def get_clf_eval(y_test, pred=None, pred_proba=None):
confusion = confusion_matrix( y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)
# ROC-AUC 추가
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
# ROC-AUC print 추가
print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f},\
F1: {3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
###########################################################################
dataset = load_breast_cancer()
ftr = dataset.data
target = dataset.target
# 전체 데이터 중 80%는 학습용 데이터, 20%는 테스트용 데이터 추출
X_train, X_test, y_train, y_test=train_test_split(ftr, target, test_size=0.2, random_state=156 )
# 앞서 XGBoost와 동일하게 n_estimators는 400 설정.
lgbm_wrapper = LGBMClassifier(n_estimators=400)
# LightGBM도 XGBoost와 동일하게 조기 중단 수행 가능.
evals = [(X_test, y_test)]
lgbm_wrapper.fit(X_train, y_train, early_stopping_rounds=100, eval_metric="logloss",
eval_set=evals, verbose=True)
preds = lgbm_wrapper.predict(X_test)
pred_proba = lgbm_wrapper.predict_proba(X_test)[:, 1]
get_clf_eval(y_test, preds, pred_proba)
4. Stacking
개별 알고리즘의 예측 결과 데이터 세트를 최종적인 메타 데이터 세트로 만들어 별도의 ML알고리즘으로 최종 핛ㅂ을 수행하는 방식 ("메타모델")
즉, 스태킹 모델은 두종류의 모델이 필요함. 첫번째는 개별적인 "기반 모델"이고, 두번째는 이 개발 기반 모델의 예측 데이터를 학습데이터로 만들어서 학습하는 최종 "메타모델"
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
cancer_data = load_breast_cancer()
X_data = cancer_data.data
y_label = cancer_data.target
X_train , X_test , y_train , y_test = train_test_split(X_data , y_label , test_size=0.2 , random_state=0)
# 개별 ML 모델을 위한 Classifier 생성.
knn_clf = KNeighborsClassifier(n_neighbors=4)
rf_clf = RandomForestClassifier(n_estimators=100, random_state=0)
dt_clf = DecisionTreeClassifier()
ada_clf = AdaBoostClassifier(n_estimators=100)
# 최종 Stacking 모델을 위한 Classifier생성.
lr_final = LogisticRegression(C=10)
# 개별 모델들을 학습.
knn_clf.fit(X_train, y_train)
rf_clf.fit(X_train , y_train)
dt_clf.fit(X_train , y_train)
ada_clf.fit(X_train, y_train)
# 학습된 개별 모델들이 각자 반환하는 예측 데이터 셋을 생성하고 개별 모델의 정확도 측정.
knn_pred = knn_clf.predict(X_test)
rf_pred = rf_clf.predict(X_test)
dt_pred = dt_clf.predict(X_test)
ada_pred = ada_clf.predict(X_test)
print('KNN 정확도: {0:.4f}'.format(accuracy_score(y_test, knn_pred)))
print('랜덤 포레스트 정확도: {0:.4f}'.format(accuracy_score(y_test, rf_pred)))
print('결정 트리 정확도: {0:.4f}'.format(accuracy_score(y_test, dt_pred)))
print('에이다부스트 정확도: {0:.4f} :'.format(accuracy_score(y_test, ada_pred)))
pred = np.array([knn_pred, rf_pred, dt_pred, ada_pred])
print(pred.shape)
# transpose를 이용해 행과 열의 위치 교환. 컬럼 레벨로 각 알고리즘의 예측 결과를 피처로 만듦.
pred = np.transpose(pred)
print(pred.shape)
lr_final.fit(pred, y_test)
final = lr_final.predict(pred)
print('최종 메타 모델의 예측 정확도: {0:.4f}'.format(accuracy_score(y_test , final)))
ㅁ ensemble 알고리즘별 sklearn API
ensemble 유형 | 알고리즘 | sklearn API | hyper-parameter |
bagging | random foreset | from sklearn.ensemble import RandomForestClassifier RandomForestClassifier() |
- n_estimators : 결정트리 개수 - max_features - max_depth - min_samples_leaf 등 |
boosting | GBM (Gradient Boost Machine) | from sklearn.ensemble import GradientBoostingClassifier GradientBoostingClassifier() |
- n_estimators - loss - learning_rate - subsample 등 |
boosting | XGBoost (eXtra Gradient Boost) | from xgboost import XGBClassifier XGBClassifier() |
- n_estimators - learning_rate - subsample - reg_lambda - reg_alpha 등 |
boosting | LightGBM | from lightgbm import LGBMClassifier LGBMClassifier() |
- n_estimators - learning_rate - subsample - reg_lambda - reg_alpha 등 |
ㅁ Reference
- [책] 파이썬 머신러닝 완벽가이드
- [블로그] 파이썬 머신러닝 완벽가이드 정리본 (Link)
- [소스코드 출처] : https://github.com/wikibook/pymldg-rev