2023 빅리더 프로젝트 인턴십/ML

[ML] day5 지도 학습 - 앙상블 학습

혜o_n 2023. 7. 22. 02:14

* 앙상블 학습 ( ensemble learning )

 - 여러 가지 지도학습 알고리즘을 조합해서 데이터를 학습

 - 트레이닝 데이터를 활용한 분류 모형을 여러 개 만들고 비교

 - 개별 분류 모형을 분류기( classifier ) 

 - 성능이 낮은 분류기를 조합해 성능 좋은 분류기 생성

 

 보팅 ( Voting )

* 보팅

: 여러 가지 지도학습 알고리즘의 결과를 투표를 통해 최종 라벨 지정

 

 

* 실습

import pandas as pd
df = pd.read_csv('./data/wine_data.csv')

features = ['Alcohol', 'Malic', 'Ash', 'Alcalinity', 'Magesium', 'Phenols',
       'Flavanoids', 'Nonflavanoids', 'Proanthocyanins', 'Color', 'Hue',
       'Dilution', 'Proline']

X = df[features]
y = df['class']

# 트레이닝/테스트 데이터 분할
from sklearn.model_selection import train_test_split
X_tn, X_te, y_tn, y_te = train_test_split(X, y, random_state=0)

# 데이터 표준화
from sklearn.preprocessing import StandardScaler
std_scale = StandardScaler()
std_scale.fit(X_tn)
X_tn_std = std_scale.transform(X_tn)
X_te_std = std_scale.transform(X_te)

 

# 보팅 학습
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import VotingClassifier

clf1 = LogisticRegression()
clf2 = svm.SVC(kernel='linear')
clf3 = GaussianNB()

clf_voting = VotingClassifier(
                estimators=[
                    ('lr', clf1),
                    ('svm', clf2),
                    ('gnb', clf3)
                ],
                voting='hard',
                weights=[1,1,1])

clf_voting.fit(X_tn_std, y_tn)

- v o t i n g

        - hard : 많이 나온 클래스값을 예측값으로 사용

        - soft : 결과값 ( 각 클래스별 예측 확률의 평균값 ) 이 가장 높은 값을 예측값으로 사용

        => 두 개의 차이가 크게 존재하지 않음

# 예측
pred_voting = clf_voting.predict(X_te_std)
print(pred_voting)

### 결과값 ###
[0 2 1 0 1 1 0 2 1 1 2 2 0 1 2 1 0 0 1 0 1 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0 2
 1 1 2 0 0 1 1 1]

 

# 정확도 
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_te, pred_voting)
print("accuracy:", accuracy)

# 정밀도 
from sklearn.metrics import precision_score
precision = precision_score(y_te, pred_voting, average='macro')
print("precision:", precision)

# 리콜 
from sklearn.metrics import recall_score
recall = recall_score(y_te, pred_voting, average='macro')
print("recall:", recall)

# F1 스코어
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_voting, average='macro')
print("f1:", f1)

### 결과값 ###
accuracy: 1.0
precision: 1.0
recall: 1.0
f1: 1.0

 

# confusion matrix 확인
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_te, pred_voting)
print(conf_matrix)

### 결과물 ###
[[16  0  0]
 [ 0 21  0]
 [ 0  0  8]]

 

# 분류 레포트 확인
from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_voting)
print(class_report)

### 결과물 ###
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        16
           1       1.00      1.00      1.00        21
           2       1.00      1.00      1.00         8

    accuracy                           1.00        45
   macro avg       1.00      1.00      1.00        45
weighted avg       1.00      1.00      1.00        45

 

 배깅 (Bagging)

* 배깅(bagging)

- 개별 분류기들의 분류 결과를 종합 후 최종 분류기 성능 향상

- 부트스트랩(bootstrap) 샘플을 뽑아 학습

- 부트스트랩(bootstrap) : 중복을 허용한 랜덤 샘플 방법을 의미

==> 랜덤으로 샘플을 뽑아 학습 like 미니배치 minibatch

 

* 랜덤 포레스트 (Random Forest)

 

 - training 데이터에서 중복을 허용하여 랜덤 샘플링(bootstrap) ==> 배깅(bagging)

 - feature 선택 시에는 중복이 허용 안됨

 

* 실습 ( 랜덤 포레스트 )

import pandas as pd
df = pd.read_csv('./data/wine_data.csv')

features = ['Alcohol', 'Malic', 'Ash', 'Alcalinity', 'Magesium', 'Phenols',
       'Flavanoids', 'Nonflavanoids', 'Proanthocyanins', 'Color', 'Hue',
       'Dilution', 'Proline']

X = df[features]
y = df['class']

# 트레이닝/테스트 데이터 분할
from sklearn.model_selection import train_test_split
X_tn, X_te, y_tn, y_te = train_test_split(X, y, random_state=0)

# 데이터 표준화
from sklearn.preprocessing import StandardScaler
std_scale = StandardScaler()
std_scale.fit(X_tn)
X_tn_std = std_scale.transform(X_tn)
X_te_std = std_scale.transform(X_te)

 

# 랜덤포레스트 
from sklearn.ensemble import RandomForestClassifier
clf_rf = RandomForestClassifier(max_depth=2,
                                random_state=0)
clf_rf.fit(X_tn_std, y_tn)

 - max_depth : 각 decision tree의 깊이

- 의사 결정 나무는 데이터 표준화를 안하는게 결과가 좋은 경우 有

    ( ∵ 파이썬의 IF문과 비슷한 로직이므로 단위의 영향을 받지 않음 )

ex) 유치원생의 키 : 100 & 대학생의 키 : 180

      표준화 하면 유치원생 : 0.6 & 대학생 : 1.3 

 => 표준화를 하면 격차가 적어짐

# 예측 
pred_rf = clf_rf.predict(X_te_std)
print(pred_rf)

### 결과값 ###
[0 2 1 0 1 1 0 2 1 1 2 2 0 1 2 1 0 0 2 0 0 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0 2
 1 1 2 0 0 1 1 1]

 

# 정확도 
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_te, pred_rf)
print("accuracy:", accuracy)

# 정밀도 
from sklearn.metrics import precision_score
precision = precision_score(y_te, pred_rf, average='macro')
print("precision:", precision)

# 리콜 
from sklearn.metrics import recall_score
recall = recall_score(y_te, pred_rf, average='macro')
print("recall:", recall)

# F1 스코어
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_rf, average='macro')
print("f1:", f1)

### 결과값 ###
accuracy: 0.9555555555555556
precision: 0.943355119825708
recall: 0.9682539682539683
f1: 0.9536244800950685

 

# confusion matrix 확인
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_te, pred_rf)
print(conf_matrix)

### 결과값 ###
[[16  0  0]
 [ 1 19  1]
 [ 0  0  8]]

 

# 분류 레포트 확인
from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_rf)
print(class_report)

### 결과값 ###
              precision    recall  f1-score   support

           0       0.94      1.00      0.97        16
           1       1.00      0.90      0.95        21
           2       0.89      1.00      0.94         8

    accuracy                           0.96        45
   macro avg       0.94      0.97      0.95        45
weighted avg       0.96      0.96      0.96        45

 

* 실습 ( 배깅 bagging )

# 배깅 학습
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import BaggingClassifier
clf_bagging = BaggingClassifier(estimator=GaussianNB(),
                                n_estimators=10,
                                random_state=0)
clf_bagging.fit(X_tn_std, y_tn)

 - n _ estimator : 모형의 갯수 즉, 하나의 분류기가 모델을 시행하는 횟수

 - 위의 예제는 나이브 베이즈 알고리즘 사용 ( default는 의사결정나무)

# 예측
pred_bagging = clf_bagging.predict(X_te_std)
print(pred_bagging)

### 결과값 ###
[0 2 1 0 1 1 0 2 1 1 2 2 0 1 2 1 0 0 2 0 0 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0 2
 1 1 2 0 0 1 1 1]

 

# 정확도 
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_te, pred_bagging)
print("accuracy:", accuracy)

# 정밀도 
from sklearn.metrics import precision_score
precision = precision_score(y_te, pred_bagging, average='macro')
print("precision:", precision)

# 리콜 
from sklearn.metrics import recall_score
recall = recall_score(y_te, pred_bagging, average='macro')
print("recall:", recall)

# F1 스코어
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_bagging, average='macro')
print("f1:", f1)

### 결과값 ###
accuracy: 0.9555555555555556
precision: 0.943355119825708
recall: 0.9682539682539683
f1: 0.9536244800950685

 

# confusion matrix 확인
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_te, pred_bagging)
print(conf_matrix)

### 결과값 ###
[[16  0  0]
 [ 1 19  1]
 [ 0  0  8]]

 

# 분류 레포트 확인
from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_bagging)
print(class_report)

### 결과값 ###
              precision    recall  f1-score   support

           0       0.94      1.00      0.97        16
           1       1.00      0.90      0.95        21
           2       0.89      1.00      0.94         8

    accuracy                           0.96        45
   macro avg       0.94      0.97      0.95        45
weighted avg       0.96      0.96      0.96        45

 

 부스팅 ( Boosting )

* 부스팅 ( boosting )

- 분류하기 어려운 데이터 포인트에 가중치를 할당

- 학습이 진행되면서 올바르게 분류된 데이터의 가중치는 감소 / 잘못 분류된 데이터의 가중치는 증가

==> 학습이 진행되면서 학습기는 분류하기 어려운 데이터에 집중

보팅, 배깅과 다르게 parallel 하지 않음 

=> 예를 들어 보팅, 배깅은 여러명이 동시에 문제를 풀지만 부스팅은 한명식 차례로 문제를 품

 

* 실습

# 에이다 부스트
from sklearn.ensemble import AdaBoostClassifier
clf_ada = AdaBoostClassifier(random_state=0)
clf_ada.fit(X_tn_std, y_tn)

 

# 예측
pred_ada = clf_ada.predict(X_te_std)
print(pred_ada)

### 결과값 ###
[0 2 0 0 1 0 0 2 1 1 2 2 0 0 2 1 0 0 1 0 0 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0 2
 1 0 2 1 0 1 1 1]

 

# 정확도 
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_te, pred_ada)
print("accuracy:", accuracy)

# 정밀도 
from sklearn.metrics import precision_score
precision = precision_score(y_te, pred_ada, average='macro')
print("precision:", precision)

# 리콜 
from sklearn.metrics import recall_score
recall = recall_score(y_te, pred_ada, average='macro')
print("recall:", recall)

# F1 스코어
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_ada, average='macro')
print("f1:", f1)

### 결과물 ###
accuracy: 0.8666666666666667
precision: 0.8970588235294118
recall: 0.8998015873015873
f1: 0.8918128654970761

 

# confusion matrix 확인
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_te, pred_ada)
print(conf_matrix)

### 결과물 ###
[[15  1  0]
 [ 5 16  0]
 [ 0  0  8]]

 

# 분류 레포트 확인
from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_ada)
print(class_report)

### 결과물 ###
              precision    recall  f1-score   support

           0       0.75      0.94      0.83        16
           1       0.94      0.76      0.84        21
           2       1.00      1.00      1.00         8

    accuracy                           0.87        45
   macro avg       0.90      0.90      0.89        45
weighted avg       0.88      0.87      0.87        45

 

* 실습 ( 그래디언트 부스팅 )

# Gradient Boosting 학습
from sklearn.ensemble import GradientBoostingClassifier
clf_gbt = GradientBoostingClassifier(max_depth=2,
                                     learning_rate=0.1,
                                     random_state=0)
clf_gbt.fit(X_tn_std, y_tn)

 

# 예측
pred_gbt = clf_gbt.predict(X_te_std)
print(pred_gbt)

### 결과값 ###
[0 2 1 0 1 0 0 2 1 1 2 2 0 1 2 1 0 0 2 0 1 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0 2
 1 1 2 0 0 1 1 1]

 

# 정확도 
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_te, pred_gbt)
print("accuracy:", accuracy)

# 정밀도 
from sklearn.metrics import precision_score
precision = precision_score(y_te, pred_gbt, average='macro')
print("precision:", precision)

# 리콜 
from sklearn.metrics import recall_score
recall = recall_score(y_te, pred_gbt, average='macro')
print("recall:", recall)

# F1 스코어
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_gbt, average='macro')
print("f1:", f1)

### 결과값 ###
accuracy: 0.9555555555555556
precision: 0.943355119825708
recall: 0.9682539682539683
f1: 0.9536244800950685

 

# confusion matrix 확인
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_te, pred_gbt)
print(conf_matrix)

### 결과값 ###
[[16  0  0]
 [ 1 19  1]
 [ 0  0  8]]

 

# 분류 레포트 확인
from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_gbt)
print(class_report)

### 결과물 ###
              precision    recall  f1-score   support

           0       0.94      1.00      0.97        16
           1       1.00      0.90      0.95        21
           2       0.89      1.00      0.94         8

    accuracy                           0.96        45
   macro avg       0.94      0.97      0.95        45
weighted avg       0.96      0.96      0.96        45

 

 스태킹 ( Stacking )

* 스태킹 (stacking)

- 여러 가지 학습기를 쌓는 방법

- 스태킹 : 베이스 학습기(base learner)와 메타 학습기(meta learner)

- 베이스 학습기가 먼저 학습

- 메타 학습기는 베이스 학습기의 예측을 피처 데이터로 활용해 최종 예측

 

* 실습

# 스태킹
from sklearn import svm
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import StackingClassifier

clf1 = svm.SVC(kernel='linear', random_state=1)
clf2 = GaussianNB()

clf_stkg = StackingClassifier(
    estimators=[
        ('svm', clf1),
        ('gnb', clf2)
    ],
    final_estimator=LogisticRegression())
clf_stkg.fit(X_tn_std, y_tn)

 - 베이스 학습기 : 서포트 벡터 머신 & 나이브 베이즈 알고리즘

 - 메타 학습기 : 로지스틱 회귀분석

# 예측
pred_stkg = clf_stkg.predict(X_te_std)
print(pred_stkg)

### 결과값 ###
[0 2 1 0 1 1 0 2 1 1 2 2 0 1 2 1 0 0 2 0 0 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0 2
 1 1 2 0 0 1 1 1]

 

# 정확도 
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_te, pred_stkg)
print("accuracy:", accuracy)

# 정밀도 
from sklearn.metrics import precision_score
precision = precision_score(y_te, pred_stkg, average='macro')
print("precision:", precision)

# 리콜 
from sklearn.metrics import recall_score
recall = recall_score(y_te, pred_stkg, average='macro')
print("recall:", recall)

# F1 스코어
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_stkg, average='macro')
print("f1:", f1)

### 결과값 ###
accuracy: 0.9555555555555556
precision: 0.943355119825708
recall: 0.9682539682539683
f1: 0.9536244800950685

 

# confusion matrix 확인
from sklearn.metrics import confusion_matrix
conf_matrix = confusion_matrix(y_te, pred_stkg)
print(conf_matrix)

### 결과값 ###
[[16  0  0]
 [ 1 19  1]
 [ 0  0  8]]

 

# 분류 레포트 확인
from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_stkg)
print(class_report)

### 결과값 ###
              precision    recall  f1-score   support

           0       0.94      1.00      0.97        16
           1       1.00      0.90      0.95        21
           2       0.89      1.00      0.94         8

    accuracy                           0.96        45
   macro avg       0.94      0.97      0.95        45
weighted avg       0.96      0.96      0.96        45