본문 바로가기
머신러닝/앙상블 기법

앙상블 기법 - Boosting Algorithm

by 미생22 2024. 5. 20.
728x90

- 앙상블은 전통적으로 Voting, Bagging, Boosting, 스태깅 등으로 나눔

- 보팅과 배깅은 여러개의 분류기가 투표를 통해 최종 예측 결과를 결정하는 방식

- 보팅과 배깅의 차이점은 보팅은 각각 다른 분류기, 배깅은 같은 분류기를 사용

- 대표적인 배깅 방식이 랜덤 포레스트

 

*Voting과 Bagging 의 차이

즉 Voting 방법은 전체 데이터를 각각 다른 알고리즘으로 돌리는것,

Baaging 방법은 하나의 알고리즘을 쓰는데 전체 데이터를 나눠서 쓴다는 것. 나누는 방법이 중복을 허락해서(bootstraping) 수집한다.

 

* Boosting기법

Boosting 방법은 여러개의 약한 분류기(성능이 떨어지고 빠른 방법)를 학습하면서, 앞에서 학습한 분류기가 예측이 틀린 데이터에 의해 다음 분류기가 가중치를 인가해서 학습을 이어가는 방식, 대표적으로 그래디언트 부스트 방법, XGBoost(eXtra Gradient Boost), LightGBM (Light Gradient Boost) 등이 있다. LightGBM이 인기가 있다고 한다.

- GBM(Gradient Boosting Machine) : AdaBoost 기법과 비슷하지만, 가중치를 업데이트 할 때 경사하강법(Gradient Descent)을 사용

- XGBoost(eXtra Gradient Boost) : GBM에서 PC의 파워를 효율적으로 사용하기 위한 다양한 기법에 채택되어 빠른 속도와 효율을 가짐, GBM과 비슷한데 하드웨어를 많이 썼다(GPU를 쓸수있게함)고 생각하면 된다.

- LightGBM : XGBoost보다 빠른 속도를 가짐

 

 

*Bagging과 Boosting의 차이

Bagging은 데이터를 통으로 쓰던, 잘라서 쓰던 학습하는 타이밍이 동시에 이루어집니다. 데이터들이 각각의 분류기에 들어가고 분류기에서 한번에 돌아갑니다. Boosting은 데이터로 분류기를 돌리고 가중치를 준뒤 또 학습하고 그 결과를 가중치를 준뒤 또 학습합니다. 따라서 순차적으로 진행됩니다.

 

*Adaboost기법

약한 분류기를 돌리기 때문에 맨처음에는 보통 틀립니다. 결과가 아래 그림처럼 나옵니다.

이 후 오른쪽 파란+ 세 점에 가중치를 줍니다.

이랬더니 아래 -세점이 틀렸습니다. 여기에 가중치를 줍니다.

이 세개를 합칩니다.

이게 Boosting 정렬의 기본입니다.

 

이제 Boosting algorithm을 이전의 와인데이터를 가지고 살펴보겠습니다.

 

import pandas as pd

wine_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/wine.csv'

wine = pd.read_csv(wine_url, index_col=0)

wine['taste'] = [1. if grade>5 else 0. for grade in wine['quality']]

X = wine.drop(['taste', 'quality'], axis=1)
y = wine['taste']

 

이번에는 pipeline이 아니라 직접 Standard Scaler를 적용해보겠습니다.

 

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
X_ss = ss.fit_transform(X)

 

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_ss, y, test_size=0.2, random_state=13)

 

여기서 histogram으로 데이터들이 잘 분포되어 있는지 확인해보겠습니다.

 

import matplotlib.pyplot as plt

wine.hist(bins=10, figsize=(15, 10));

보통 정규분포 함수 즉 잘 분포되어 있는 컬럼이 좋을 때가 많습니다. pH, total surfur dioxide 같은 애들이 되겠네요.

quality별로 다른 특성이 있는지 확인해보겠습니다.

 

wine.columns를 추출하고 거기서 quality, color, taste를 빼겠습니다.

 

column_names = ['fixed acidity', 'volatile acidity', 'citric acid', 'residual sugar',
       'chlorides', 'free sulfur dioxide', 'total sulfur dioxide', 'density',
       'pH', 'sulphates', 'alcohol']
df_pivot_table = wine.pivot_table(column_names, ['quality'], aggfunc='median')
df_pivot_table

 

quality에 대한 나머지 특징들의 상관관계를 보겠습니다.

 

corr_matrix = wine.corr()
corr_matrix['quality'].sort_values(ascending=False)

여기서 중요한점은 절대값으로 봐야 관계성이 높다는 것입니다. +와 -는 비례하는 정도가 높을수록인지 낮을수록인지를 판단하는 것 뿐입니다.

이제 label인 taste 컬럼의 분포를 살펴보겠습니다.

 

import seaborn as sns

sns.countplot(wine['taste'])
plt.show()

이번에는 부스팅 알고리즘을 포함한 다양한 모델을 한번에 테스트해보고 싶습니다.

 

from sklearn.ensemble import AdaBoostClassifier, GradientBoostingClassifier, RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression

models = []
models.append(('RandomForestClassifier', RandomForestClassifier()))
models.append(('DecisionTreeClassifier', DecisionTreeClassifier()))
models.append(('AdaBoostClassifier', AdaBoostClassifier()))
models.append(('GradientBoostingClassifier', GradientBoostingClassifier()))
models.append(('LogisticRegression', LogisticRegression()))

 

모델 리스트에 append 할 때 () 즉 튜플형태로 이름과 instanciation시킨 함수를 같이 넣어줍니다.

 

이제 결과를 저장하기 위한 작업을 합니다.
KFold와 cross_val_score를 들고옵니다.
참고로 KFold와 cross_val_score는 모델이 새로운 데이터에 얼마나 잘 일반화되는지 확인합니다.
참고로 복습하자면 Recall(재현율), Precision(정밀도), F1 Score는 모델의 분류 성능을 측정하는 지표입니다.

from sklearn.model_selection import KFold, cross_val_score

results = []
names = []

for name, model in models:
    kfold = KFold(n_splits=5, random_state=13, shuffle=True) #shuffle은 data를 5개로 나누기 전에 섞을것인가에 대한 옵션입니다.
    cv_results = cross_val_score(model, X_train, y_train, cv=kfold, scoring='accuracy')
    results.append(cv_results)
    names.append(name)

    print(name, cv_results.mean(), cv_results.std())

여기서 KFold의 옵션으로 shuffle은 data를 5개로 나누기 전에 섞을 것인가에 대한 옵션입니다.

 

 

이제 results를 살펴보면 아래와 같습니다. 5개 알고리즘에 대한 5개 fold의 성능이 들어있습니다.

 

 

cv_results.mean() 결과를 보면 random forest가 가장 좋은 성능을 보입니다.
training 된 평균값만 본다면 cv_results.mean()를 보면 그렇습니다.
cross validation 결과를 일목요연하게 확인해보겠습니다.

fig = plt.figure(figsize=(14, 8))
fig.suptitle('Algorithm Comparison')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.show()

굳이 이렇게 그래프를 복잡하게 그린 이유는 ax를 주고 xticks를 바로 주고싶었기 때문입니다.

 

지금은 random forest가 가장 유리해보입니다.
그럼 이제 테스트 데이터에 대한 평가결과를 보겠습니다.

 

from sklearn.metrics import accuracy_score

for name, model in models:
    model.fit(X_train, y_train)
    pred = model.predict(X_test)
    print(name, accuracy_score(y_test, pred))

 

728x90