티스토리 뷰

Machine Learning 입문

9. 앙상블 학습

DWD85 2024. 12. 28. 09:06

> 머신 러닝의 지도 학습 (kNN, 선형회귀, 로지스틱 회귀, 나이브 제이즈, 의사결정 나무. 서포트 벡터 머신)

> 이 머신 러닝의 알고리즘을 합체시키는 것이 앙상블 학습이 있다. 

> 합체 방법은 여러가지 (voting (투표), bagging(구걸), boosting(가속), stacking(쌓다))

> 하나의 모형을 분류기, 여러 분류기를 모아서 성능 좋은 분류기 생성

> 그래도 개별 분류기의 성능이 accuracy 기준 50%는 넘겨야 함 (동전 던지는 것보다 나아야) 권장은 60%

 

> 투표해서 결과 판단.

 

#Voting 구분
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)

pred_voting = clf_voting.predict(X_te_std)

from sklearn.metrics import classification_report
class_report = classification_report(y_te, pred_voting) 
print(class_report)

 

from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import VotingRegressor

clf1 = LinearRegression()
clf2 = SVR(kernel = 'linear')
clf3 = DecisionTreeRegressor()

clf_voting = VotingRegressor(estimators=[('lr', clf1), ('svm', clf2), ('tree', clf3)], 
                             weights = [1,1,1])
clf_voting.fit(X_tn_std, y_tn)
vote_pred = clf_voting.predict(X_te_std)

from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_te, vote_pred))

> lr, svm, gnb는 nickname 

> voting은 hard (표를 세는 거), soft는 각 class 별 확률의 argmax

> soft는 다 쓸 수 없고 확률이 나와야 사용 가능하다 (kNN은 확률이 없어서 못 씀)

> weight는 가중치, 좀 더 똑똑한 애한테 더 가중치를 주는 것. 

> 회귀는 투표 방식이 없고 몇 개의 평균으로 예측한다. 

 

> Bootstrap 방법을 사용, 중복을 허용한 랜덤 샘플링 (복원 추출)

 

> bagging에서 매우 유명한 Random Forest 

> Decision Tree와 관련이 있고 나무를 많이 만든다

 

> bagging : bootstrap aggregating (복원 랜덤 추출해서 집계하다) 

 

> 피처도 d개 뽑는데 중복 허용을 안되게 한다 

 

> 4개 중 2개 뽑는다 4C2

> 모든 나무가 다르고 나무의 결과를 투표 붙여서 결과를 도출한다 

> 오버 피팅을 해결할 수 있다.

> Voting과의 차이점은 서로 다른 분류기를 사용했는데 bagging은 분류기가 똑같은걸 여러 번 사용한다.

 

 

#bagging 구분
from sklearn.ensemble import RandomForestClassifier
clf_rf = RandomForestClassifier(max_depth =10, random_state = 0)
clf_rf.fit(X_tn_std, y_tn)

pred_rf = clf_rf.predict(X_te_std)
print(classification_report(y_te, pred_rf))

 

#bagging 회귀
from sklearn.ensemble import RandomForestRegressor
clf_rfr = RandomForestRegressor(max_depth =2, random_state = 0) 
clf_rfr.fit(X_tn_std, y_tn) 

pred_rfr = clf_rfr.predict(X_te_std)
print(mean_squared_error(y_te,pred_rfr))

 

> max_depth 나무의 깊이

> feature_importance_는 impurity based로 한다(엔트로피 느낌) 

> random_forest = bagging은 아니다 random forest가 bagging 하나의 방법이다. 

 

#bagging 분류
import pandas as pd
import numpy as np 

df = pd.read_csv('./data/wine_data.csv', encoding = 'cp949')

X = df[['Alcohol', 'Malic', 'Ash', 'Alcalinity', 'Magesium', 'Phenols',
       'Flavanoids', 'Nonflavanoids', 'Proanthocyanins', 'Color', 'Hue',
       'Dilution', 'Proline']]
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_scaler = StandardScaler()
std_scaler.fit(X_tn)

X_tn_std = std_scaler.transform(X_tn)
X_te_std = std_scaler.transform(X_te)

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) 
pred_clf = clf_bagging.predict(X_te_std)

from sklearn.metrics import classification_report 
print(classification_report(y_te, pred_clf))

 

#bagging 예측
df1 = pd.read_csv('./data/house_prices.csv', encoding = 'cp949')
X1 = df1[['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
       'PTRATIO', 'B', 'LSTAT']]
y1 = df1['MEDV']

from sklearn.model_selection import train_test_split
X1_tn, X1_te, y1_tn, y1_te = train_test_split(X1, y1, random_state = 0)

from sklearn.preprocessing import StandardScaler
std_scaler = StandardScaler()
std_scaler.fit(X1_tn) 

X1_tn_std = std_scaler.transform(X1_tn) 
X1_te_std = std_scaler.transform(X1_te)

from sklearn.svm import SVR
from sklearn.ensemble import BaggingRegressor 
rg_bagging = BaggingRegressor(estimator = SVR(), n_estimators = 10, random_state =0)
rg_bagging.fit(X1_tn_std, y1_tn) 

pred_rg = rg_bagging.predict(X1_te_std)

from sklearn.metrics import mean_squared_error 
mse = mean_squared_error(y1_te, pred_rg)
print(mse)

 

> Bagging은 같은 모델을 여러 개 만드는 걸 말한다

> 같은 모델이 decision tree이면 Random Forest가 되는 것이다. 

> 다른 모델도 가능하다. 

 

> 오답 노트처럼 틀린 문제를 집중하는 걸 부스팅이라고 한다. 

> Voting, Bagging과 다른 점은 병렬 처리가 아니라 수직적인 구조를 갖고 있다.

> 여러 학습기 중 앞의 연산자가 끝나야 다음 모델 시작 가능 

> 그래서 Voting, Bagging 보단 부하가 걸릴 수 있다. 

> 학습할 내용은 ada boost, gradient boost

> Adaboost에서 사용하는 기본 학습기는 결정 트리(Decision Tree)이고 Max Depth가 1이다.

 

#ada boost 분류 
from sklearn.ensemble import AdaBoostClassifier 
clf_ada = AdaBoostClassifier(random_state =0,
                            algorithm = 'SAMME',
                            n_estimators = 50)
clf_ada.fit(X_tn_std, y_tn) 

pred_ada = clf_ada.predict(X_te_std)

from sklearn.metrics import classification_report 
print(classification_report(y_te, pred_ada))

> Default 값인 SAMME.R 알고리즘이 차후 업데이트에서 더 이상 사용되지 않을 예정으로 변경 

 

#ada boost 회귀 
from sklearn.ensemble import AdaBoostRegressor 
rg_ada = AdaBoostRegressor(random_state=0)

rg_ada.fit(X1_tn_std, y1_tn)
rg_ada.fit(X1_tn_std, y1_tn)
pred_rg = rg_ada.predict(X1_te_std)
from sklearn.metrics import mean_squared_error 
print(mean_squared_error(y1_te, pred_rg))

 

> 한때 인기가 있었던 앙상블 모델 (Xg boost, sklearn엔 없음)

> 타깃 y = 타깃 추정치 y^ + 에러 e

> y^가 f(x)이고 f(x)를 잘 구하면 e가 작아진다.

> gardient boosting은 e를 추정하는 g(x) 함수를 만들고 남는 e를 입실론이 추가된다.

> gradient boosting은 타깃과 에러를 추정해서 에러를 좀 더 줄이는 방법 

> 기본 학습기는 tree이다.

 

#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)

from sklearn.metrics import confusion_matrix 
print(confusion_matrix(y_te, pred_gbt))

from sklearn.metrics import classification_report
print(classification_report(y_te, pred_gbt))

#gradient boosting 예측
from sklearn.ensemble import GradientBoostingRegressor 
rg_gbt = GradientBoostingRegressor(max_depth =2, learning_rate = 0.1, random_state =0) 
rg_gbt.fit(X1_tn_std, y1_tn) 
pred_gbt1 = rg_gbt.predict(X1_te_std)

from sklearn.metrics import mean_squared_error 
print(mean_squared_error(y1_te, pred_gbt1))

> learning rate는 gradient에서 한 걸음의 크기를 나타냄. 

 

 

> training data에서 일부분 빼서 학습을 한 예측 결과들을 가직고 피쳐를 만들어서 메타 학습기로 최종 예측을 한다

> 장점은 결과가 잘 나온다.  

> 베타 학습기 final_estimator이고 base 학습기와 다를 수 있다.

> 쌓는 분류기에 예측기 모델을 넣으면 안 된다. 

 

#stacking 분류기 
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') 
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)

from sklearn.metrics import classification_report 
print(classification_report(y_te, pred_stkg))

 

#stacking 회귀 
from sklearn.svm import SVR 
from sklearn.tree import DecisionTreeRegressor 
from sklearn.linear_model import LinearRegression 
from sklearn.ensemble import StackingRegressor 

rg1 = SVR(kernel = 'linear')
rg2 = DecisionTreeRegressor(random_state =0)

rg_stkg = StackingRegressor(estimators=[('svm',rg1), ('tree', rg2)],
                             final_estimator = LinearRegression())
rg_stkg.fit(X1_tn_std, y1_tn)
pred1_stkg = rg_stkg.predict(X1_te_std)

from sklearn.metrics import mean_squared_error
print(mean_squared_error(y1_te, pred1_stkg))

 

 

> Validation을 추가해서 Training Data를 Train과 Validation으로 나눠서 Hyper Parameter를 최적화되도록 한다.

 

> 5 Fold Cross Validation

 

> 찾고 싶은 parameter를 grid 형태로 만든다 param_grid 

> StratifiedFold 함수 (비율 맞추는 함수) 사용한다. 

> Shuffle은 섞는다. 

> GrideSearch는 param_grid 후보를 다 넣어보는 함수 

> scoring은 가장 좋은 거 찾는 것이고 그 기준. 

> 모형이 8개 나와야 함

> 8개 후보가 나온다

> mean fit time : 학습에 걸린 평균 시간 

> fold를 5번 했기 때문에 split0~4 5개의 결과 나온다. 

> rank 는 어떤 조합이 몇 등 했는지 나온다. 

> 너무 많은 parameter는 연산이 어렵다. 

 

#cross validation 분류
from sklearn import svm
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import GridSearchCV

param_grid = {'kernel': ('linear', 'rbf'), 'C' : [0.5, 1, 10, 100] }
kfold  = StratifiedKFold(n_splits =5, shuffle=True, random_state =0) 
svc = svm.SVC(random_state =0) 
grid_cv = GridSearchCV(svc, param_grid, cv=kfold, scoring ='accuracy') 
grid_cv.fit(X_tn_std, y_tn) 

np.transpose(pd.DataFrame(grid_cv.cv_results_))

print(grid_cv.best_score_)
print(grid_cv.best_params_)
print(grid_cv.best_estimator_)
clf = grid_cv.best_estimator_

 

 

from sklearn.model_selection import cross_validate 
metrics = ['accuracy', 'precision_macro', 'recall_macro', 'f1_macro']
cv_scores = cross_validate(clf, X_tn_std, y_tn, cv =kfold, scoring = metrics)
print(np.transpose(pd.DataFrame(cv_scores)))

 

from sklearn.model_selection import cross_val_score
cv_score = cross_val_score(clf, X_tn_std, y_tn, cv=kfold, scoring='accuracy')
print(cv_score)
print(cv_score.mean())
print(cv_score.std())

 

pred_svm = clf.predict(X_te_std)

from sklearn.metrics import classification_report 
print(classification_report(y_te, pred_svm))

 

 

> 예측에서 차이는 그냥 KFold 들어간다 

> 예측은 연속형 데이터기 때문에 비율로 나눌 필요가 없다 

> neg_mean_squared_error는 (-) 값 붙인 mse 

> mse는 망소 항목이기 때문에 -값이 클 때 좋은 값이 나온다. 

 

#cross validation 예측
from sklearn import svm
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV

kfold = KFold(n_splits =5, shuffle = True, random_state = 0)
param_grid = {'kernel' : ('linear', 'rbf'), 'C' : [0.5, 1, 10, 100]}
svr = svm.SVR() 
grid_cv = GridSearchCV(svr, param_grid, cv= kfold, scoring = 'neg_mean_squared_error')
grid_cv.fit(X1_tn_std, y1_tn) 

rg = grid_cv.best_estimator_
pred_rg = rg.predict(X1_te_std)
print(-1*grid_cv.best_score_)

from sklearn.metrics import mean_squared_error 
print(mean_squared_error(y1_te, pred_rg))

> validation이랑 차이가 날 수 있다.

> test도 최종 목적이 아니고 general 한 data에 대한 성능이 좋아야 한다. 

 

Ref : https://losskatsu.github.io/categories/#

반응형

'Machine Learning 입문' 카테고리의 다른 글

11. 시계열 분석  (0) 2024.12.28
10. 비지도 학습  (0) 2024.12.28
8. 지도 학습  (0) 2024.12.26
7. 최적화 & 모형 평가  (1) 2024.12.26
6. 확률 분포 & 가설 검정  (0) 2024.12.26
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함