728x90
기존 타이타닉 데이터를 이용하여 앙상블을 진행하겠다.
데이터 가져오기
import pandas as pd
import numpy as np
import seaborn as sns
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
df = sns.load_dataset('titanic') # 타이타닉 데이터 받아오기
cols = ["age","sibsp","parch","fare"] # 숫자니까 바로 사용
features = df[cols] # 피쳐
target = df["survived"] # 정답값
# one hot encoding
cols = ["pclass","sex","embarked"] # 범주형
enc = OneHotEncoder(handle_unknown='ignore')
tmp = pd.DataFrame(
enc.fit_transform(df[cols]).toarray(),
columns = enc.get_feature_names_out()
)
features = pd.concat([features,tmp],axis=1)
# 나이 결측치 채우기
features.age = features.age.fillna(features.age.median())
스케일링
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
features.loc[:,features.columns] = scaler.fit_transform(features) # 넘파이 형식에서 데이터프레임 형식으로 변환
마지막에 loc를 이용하여 넘파이 형식을 데이터프레임 형태로 바꾸었다.
SEED = 42
x_train,x_valid,y_train,y_valid = train_test_split(features,target,random_state=SEED,test_size=0.2)
x_train.shape,x_valid.shape,y_train.shape,y_valid.shape
=> ((712, 13), (179, 13), (712,), (179,))
학습데이터와 정답데이터를 분리하였다.
앙상블 학습(Ensemble Learning)
- 기계학습에서 여러개의 개별 모델의 예측을 결함으로써 보다 정확한 예측을 도출하는 기법
앙상블 모델
Random Forest
- 랜덤하게 일부 샘플들과 일부 피쳐들을 뽑아서 여러 개의 트리를 만들어서 앙상블하는 모델
- 배깅 방식을 이용
- 배깅(Bagging)
- Bootstrap Aggregation의 약어
- 샘플을 랜덤하게 여러번 뽑아 각 모델에 학습시켜 결과물을 집계하는 방법
from sklearn.ensemble import RandomForestClassifier
hp = {
"random_state" : SEED,
"max_features" : "sqrt", # None을 줄 경우 전체피쳐 사용
"n_estimators" : 100, # 트리개수를 의미 (잘 기억해두기)
"max_depth" : 10,
"min_samples_split" : 10,
"min_samples_leaf" : 3
}
model = RandomForestClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8952380952380953
배깅 적용 후
from sklearn.ensemble import BaggingClassifier
from sklearn.linear_model import LogisticRegression
hp = {
"random_state" : SEED,
"base_estimator" : LogisticRegression(random_state=SEED), # None이면 결정트리를 사용함
"n_estimators" : 100, # base_estomator 개수
"max_features" : 0.5 # 추출할 샘플 비율
}
model = BaggingClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8698841698841698
Voting
- 여러 모델들의 예측값을 투표방식(hard) or 평균방식(soft)으로 앙상블
soft 방식
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import VotingClassifier
estimators = [
( "mlp",MLPClassifier(max_iter=1000,random_state=SEED) ),
( "lr", LogisticRegression(random_state=SEED) ),
( "rf", RandomForestClassifier(random_state=SEED) )
]
hp = {
"estimators" : estimators,
"voting" : "soft"
}
model = VotingClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.9063063063063064
각 예측값을 평균낸다.
hard 방식
from sklearn.metrics import f1_score
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import VotingClassifier
estimators = [
( "mlp",MLPClassifier(max_iter=1000,random_state=SEED) ), # 0과 1의 과반수
( "lr", LogisticRegression(random_state=SEED) ),
( "rf", RandomForestClassifier(random_state=SEED) )
]
hp = {
"estimators" : estimators,
"voting" : "hard"
}
model = VotingClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict(x_valid)
f1_score(y_valid,pred) # 0과 1로 결정된 값
=> 0.7659574468085106
Stacking
- 여러 모델들의 예측값을 최종모델(메타모델)의 학습 데이터로 사용해서 예측하는 방법
- 과적합 방지하기 위해 내부적으로 CV를 진행한다.
from sklearn.ensemble import StackingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
estimators = [
( "knn",KNeighborsClassifier(n_neighbors=10,weights="distance") ),
( "dt", DecisionTreeClassifier(max_depth=3,random_state=SEED) ),
( "rf", RandomForestClassifier(random_state=SEED) )
]
hp = {
"estimators" : estimators,
"final_estimator" : LogisticRegression(random_state=SEED)
}
model = StackingClassifier(**hp,n_jobs = -1) # n_job -1 = cpu를 전부 다 사용하여 빠르게 나오도록한다. 있으면 무조건 사용
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8820463320463321
GradientBoosting
- 트리기반 부스팅 앙상블 모델
- 머신러닝 알고리즘 중에서 가장 예측성능이 높다고 알려졌고, 인기있는 알고리즘
- Boosting
- 약한 모델을 결합하여 강한 모델을 만드는 과정
- 배깅과 다른점은 순차적으로 모델을 만들어 각 모델의 예측결과를 결합
혹시 모르니 데이터 복사해놓기 (튜플형태로 복사됨!)
data_backup = x_train.copy(), x_valid.copy(), y_train.copy(), y_valid.copy()
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_diabetes
diabetes = load_diabetes()
data = diabetes.data
target = diabetes.target
data.shape, target.shape
=> ((442, 10), (442,))
데이터 셋 분리
x_train,x_valid,y_train,y_valid = train_test_split(data,target,random_state=SEED)
x_train.shape,x_valid.shape,y_train.shape,y_valid.shape
=> ((331, 10), (111, 10), (331,), (111,))
GradientBoostingRegressor 구현
hp = {
"max_depth" : 2,
"random_state" : SEED
}
weak_1 = DecisionTreeRegressor(**hp)
weak_1.fit(x_train,y_train)
pred = weak_1.predict(x_train)
residual = y_train - pred
weak_2 = DecisionTreeRegressor(**hp)
weak_2.fit(x_train,residual)
pred = weak_2.predict(x_train)
residual = residual - pred
weak_3 = DecisionTreeRegressor(**hp)
weak_3.fit(x_train,residual)
pred = weak_1.predict(x_valid) + weak_2.predict(x_valid) + weak_3.predict(x_valid)
mean_squared_error(y_valid,pred) ** 0.5 # RMSE
위 과정은 그냥 구현한 것이고, 밑에는 GradientBoostingRegressor를 사용하여 구현한 것이다.
그래서 결과값이 같다.
gbr = GradientBoostingRegressor(max_depth=2,random_state=SEED,n_estimators=3,learning_rate=1.) # 위와 같은 조건을 넣어줌!
gbr.fit(x_train,y_train)
pred = gbr.predict(x_valid)
mean_squared_error(y_valid,pred) ** 0.5
=> 61.872491186086826
- 복사한 타이타닉 데이터 복원하기
x_train, x_valid, y_train, y_valid = data_backup
from sklearn.ensemble import GradientBoostingClassifier
hp = {
"random_state" : SEED,
"max_depth" : 2,
"n_estimators" : 100, # 수행할 부스팅 단계 수
}
model = GradientBoostingClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8911196911196911
XGBoost
- 병렬처리가 불가능한 GBM의 단점을 보완
- GPU를 지원
- 내장된 교차검증과 결측치 처리같은 부가기능도 있다.
- GBM보다 속도가 향상
- 과적합 방지를 GBM보다 더 뛰어나게 방지한다.
- https://xgboost.readthedocs.io/en/stable/
from xgboost import XGBClassifier,plot_importance
hp = {
"random_state" : SEED,
"max_depth" : 2,
"n_estimators" : 100, # 수행할 부스팅 단계수
}
model = XGBClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8868082368082368
시각화
import matplotlib.pyplot as plt
plot_importance(model)
plt.show()
from xgboost import to_graphviz
to_graphviz(model)
LightGBM (많이 사용)
- XGBoost와 마찬가지로 병렬처리 및 GPU 지원
- XGB보다 학습에 걸리는 시간이 적다
- XGB보다 메모리를 훨씬 적게 사용
- https://lightgbm.readthedocs.io/en/latest/index.html
from lightgbm import LGBMClassifier, plot_importance
hp = {
"random_state" : SEED,
"max_depth" : 2,
"n_estimators" : 100, # 수행할 부스팅 단계 수
}
model = LGBMClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8821106821106821
시각화
plot_importance(model)
plt.show()
from lightgbm import create_tree_digraph
create_tree_digraph(model)
catboost
- 범주형 변수에 대하여 강력한 성능을 보여주는 GBM 기반 모델
- 범주형 변수가 많을 경우 높은 성능과 함께 속도가 lightgbm 보다 빠르다.
- 수치형 변수가 많을 경우 매우 느림
- 특징으로 범주형 변수를 인코딩 하지 않고 넣어도 된다.
- https://catboost.ai/en/docs/
코랩에서는 catboost가 없어서 설치해야한다.
!pip install catboost
from catboost import CatBoostClassifier
hp = {
"random_state" : SEED,
"max_depth" : 2,
"n_estimators" : 100, # 수행할 부스팅 단계 수
"verbose" : 0 # 부스팅 단계 출력 안보이게 하기
}
model = CatBoostClassifier(**hp)
model.fit(x_train,y_train)
pred = model.predict_proba(x_valid)[:,1]
roc_auc_score(y_valid,pred)
=> 0.8787001287001287
catboost는 높은 성능과 함께 속도가 lightgbm 보다 빠르기 때문에
수치형을 범주형으로 변경해서 넣으면 좋을 수도 있다.
앙상블을 보고, 다양한 모델들을 각자 합리적인 방법으로 적용시키는 것이 신기하였다.
이것도 각 특징을 잘 알고, 잘써야겠다는 생각이 들었다.
728x90
'AI 공부 > 머신러닝' 카테고리의 다른 글
(머신러닝) 비지도 학습 - 차원축소 (1) | 2022.09.14 |
---|---|
(머신러닝) 모델튜닝 (1) | 2022.09.13 |
(머신러닝) 머신러닝 모델 (2) | 2022.09.13 |
(머신러닝) sklearn (0) | 2022.09.11 |
(머신러닝) 교차검증과 과적합 (0) | 2022.09.07 |
댓글