1. 베이지안 최적화 이용한 XGBoost모델 돌리기
from sklearn.model_selection import train_test_split
#
num_train = len(train) # 훈련 데이터 개수
# 훈련 데이터와 테스트 데이터 나누기
X_train= all_data[:num_train] # 0~num_train -1 행
X_test = all_data[num_train:] # num_train ~ 마지막 행
y_train = train['yield'].values
y_test = submission['yield'].values
from sklearn.model_selection import GridSearchCV
import xgboost as xgb
from skopt import BayesSearchCV
# XGBoost 모델 생성
xgb_model = xgb.XGBRegressor()
# 베이지안 최적화를 위한 하이퍼파라미터 범위 정의
param_grid_xgb = {
'n_estimators': (30, 50),
'max_depth': (3, 4),
'learning_rate': (0.01, 0.3),
'subsample': (0.8, 1.0),
}
# 베이지안 최적화 객체 생성
bayes_search_xgb = BayesSearchCV(xgb_model, param_grid_xgb, scoring='neg_mean_absolute_error', cv=10, n_jobs=-1)
# 베이지안 최적화 수행
bayes_search_xgb.fit(X_train, y_train)
# 최적의 모델 및 파라미터 출력
best_model_bayes_xgb = bayes_search_xgb.best_estimator_
best_params_bayes_xgb = bayes_search_xgb.best_params_
print("Best Model (XGBoost - Bayesian):", best_model_bayes_xgb)
print("Best Parameters (XGBoost - Bayesian):", best_params_bayes_xgb)
Best Model (XGBoost - Bayesian): XGBRegressor(base_score=None, booster=None, callbacks=None,
colsample_bylevel=None, colsample_bynode=None,
colsample_bytree=None, early_stopping_rounds=None,
enable_categorical=False, eval_metric=None, feature_types=None,
gamma=None, gpu_id=None, grow_policy=None, importance_type=None,
interaction_constraints=None, learning_rate=0.12000817918154756,
max_bin=None, max_cat_threshold=None, max_cat_to_onehot=None,
max_delta_step=None, max_depth=4, max_leaves=None,
min_child_weight=None, missing=nan, monotone_constraints=None,
n_estimators=50, n_jobs=None, num_parallel_tree=None,
predictor=None, random_state=None, ...)
Best Parameters (XGBoost - Bayesian): OrderedDict([('learning_rate', 0.12000817918154756), ('max_depth', 4), ('n_estimators', 50), ('subsample', 0.8154234229224367)])
2. 베이지안 최적화와 KFOLD 이용한 LightGBM모델 돌리기
from scipy import sparse
from sklearn.model_selection import train_test_split
import lightgbm as lgb
num_train = len(train) # 훈련 데이터 개수
# 훈련 데이터와 테스트 데이터 나누기
all_data_sprs = sparse.csr_matrix(all_data)
X= all_data_sprs[:num_train] # 0~num_train -1 행
X_test = all_data_sprs[num_train:] # num_train ~ 마지막 행
y = train['yield'].values
# 8:2 비율로 훈련 데이터, 검증 데이터 분리(베이지안 최적화 수행용)
X_train , X_valid , y_train , y_valid = train_test_split(X,y, test_size=0.2 , random_state=0)
# 베이지안 최적화용 데이터셋
bayes_dtrain = lgb.Dataset(X_train , y_train)
bayes_dvalid = lgb.Dataset(X_valid, y_valid)
==> 베이지안 최적화용 데이터 셋을 생성해야한다!
2-1) 베이지안 최적화 이용한 하이퍼파라미터 찾기
# 베이지안 최적화를 위한 하이퍼파라미터 범위
param_bounds = {'num_leaves' : (30 , 50) , # 개별 트리가 가질 수 있는 최대 말단 노드 개수 , 트리 복잡도 결정, 값이 클수록 좋다.
'learning_rate' : (0.9, 1), # 학습률( 부스팅 이터레이션을 반복하면서 모델을 업데이트하는 데 사용 되는 비율)
'lambda_l1' : (0.1 , 0.2), # L1 규제 조정값 , 값이 클수록 과대적합 방지 효과
'lambda_l2' : (0.1 , 0.2), # L2 규제 조정값 , 값이 클수록 과대적합 방지 효과
'feature_fraction' : (0.6 , 0.7), # 개별 트리를 훈련할 때 사용할 피처 샘플링 비율
'bagging_fraction' : (0.6 , 0.7), # 개별 트리를 훈련할 때 사용할 데이터 샘플링 비율
'min_child_samples' : (6 , 10) , # 말단 노드가 되기 위해 필요한 최소 데이터 개수 , 값이 클수록 과대적합 방지
'min_child_weight' : (10 , 40), # 과대적합 방지 위한 값
'subsample' : (0.8,1),
}
# 값이 고정된 하이퍼파라미터
fixed_params = {'objective' : 'regression' , # 훈련 목적 , 회귀에서는 'regression' , 이진분류에서는 'binary' , 다중분류에서는 'multiclass' 사용
'bagging_freq' : 1, # 배깅 수행 빈도, 몇번의 이터레이션마다 배깅 수행할 지 결정
'force_row_wise' : True, # 메모리 용량이 충분하지 않을 때 메모리 효율을 높이는 파라미터
'random_state' : 1991} # 랜덤 시드값 (코드를 반복 실행해도 같은 결과가 나오게 지정하는 값)
==> LightGBM의 베이지안 최적화를 위한 하이퍼파라미터 범위지정(param_bounds) , 값이 고정된 하이퍼파라미터(fixed_params)
def mae_scorer(preds, dtrain):
labels = dtrain.get_label()
return 'Mae' , mean_absolute_error(labels, preds), True
==> mae로 검증시킬 함수 생성
def eval_function(num_leaves,learning_rate, lambda_l1, lambda_l2, feature_fraction, bagging_fraction, min_child_samples, min_child_weight ,subsample):
# 평가지표(MAE) 계산을 위한 함수
params = {
'num_leaves': int(round(num_leaves)),
'learning_rate' : learning_rate,
'lambda_l1': lambda_l1,
'lambda_l2': lambda_l2,
'feature_fraction': feature_fraction,
'bagging_fraction': bagging_fraction,
'min_child_samples': int(round(min_child_samples)),
'min_child_weight': min_child_weight,
'feature_pre_filter': False,
'subsample' : subsample
}
params.update(fixed_params)
print('하이퍼파라미터:', params)
# LightGBM 모델 훈련
lgb_model = lgb.train(
params=params,
train_set=bayes_dtrain,
num_boost_round=2500,
valid_sets=bayes_dvalid,
feval=mae_scorer, # 수정하지 않음: MAE 평가지표 사용
early_stopping_rounds=300,
verbose_eval=False
)
# 검증 데이터로 예측 수행
preds = lgb_model.predict(X_valid)
# MAE 계산
mae = mean_absolute_error(y_valid, preds)
print(f'MAE: {mae}\n')
return -mae # 수정하지 않음: 음수로 반환하여 최적화에 활용
==> 평가지표 함수 생성
베이지안 최적화는 주어진 하이퍼파라미터 공간에서 최적의 하이퍼파라미터 조합을 찾기 위한 최적화 알고리즘입니다. 이 알고리즘은 목적 함수의 값을 최소화하는 방향으로 탐색합니다. 따라서, 목적 함수를 최대화해야 하는 경우에는 -mae와 같이 음수로 반환하여 최적화에 활용합니다.
주어진 코드에서는 MAE(Mean Absolute Error)를 최소화해야 하므로, -mae를 반환하여 목적 함수를 최소화하도록 설정한 것입니다. 최적화 알고리즘은 이 값을 최소화하도록 하이퍼파라미터를 조정하며, 가장 작은 MAE 값을 찾아냅니다.
만약 최대화해야 하는 목적 함수가 있다면, return mae와 같이 음수가 아닌 원래의 값을 반환하면 됩니다.
from bayes_opt import BayesianOptimization
# 베이지안 최적화 객체 생성
optimizer = BayesianOptimization(f = eval_function, # 평가지표 계산 함수
pbounds = param_bounds, # 하이퍼파라미터 범위
random_state = 0 )
# 베이지안 최적화 수행
optimizer.maximize(init_points= 3 , n_iter = 6) # init_points 는 무작위로 하이퍼파라미터를 탐색하는 횟수, n_iter는 베이지안 최적화 반복 횟수
==> 베이지안 최적화 수행
==> init_points는 무작위로 하이퍼파라미터 탐색
==> n_iter는 베이지안 최적화 반복 횟수
# 평가함수 점수가 최대일 대 하이퍼파라미터
max_params = optimizer.max['params']
max_params
{'bagging_fraction': 0.7,
'feature_fraction': 0.7,
'lambda_l1': 0.1,
'lambda_l2': 0.1,
'learning_rate': 0.9,
'min_child_samples': 6.0,
'min_child_weight': 26.244142995337246,
'num_leaves': 37.513250569270674,
'subsample': 1.0}
# 정수형 하이퍼파라미터 변환
max_params['num_leaves'] = int(round(max_params['num_leaves']))
max_params['min_child_samples'] = int(round(max_params['min_child_samples']))
max_params['subsample'] = float(round(max_params['subsample'] ,2))
max_params.update(fixed_params)
#%%
max_params
{'bagging_fraction': 0.7,
'feature_fraction': 0.7,
'lambda_l1': 0.1,
'lambda_l2': 0.1,
'learning_rate': 0.9,
'min_child_samples': 6,
'min_child_weight': 26.244142995337246,
'num_leaves': 38,
'subsample': 1.000,
'objective': 'regression',
'bagging_freq': 1,
'force_row_wise': True,
'random_state': 1991}
2-2) KFold를 이용한 LightGBM의 최고 훈련 및 검증 하기
%%time
from sklearn.model_selection import StratifiedKFold ,KFold
# 층화 K 폴드 교차 검증기 생성
folds = KFold(n_splits=5 , shuffle = True , random_state= 1991)
# OOF 방식으로 훈련된 모델로 검증 데이터 타깃값을 예측한 확률을 담을 1차원 배열
oof_val_preds = np.zeros(X.shape[0])
# OOF 방식으로 훈련된 모델로 테스트 데이터 타깃값을 예측한 확률을 담을 1차원 배열
oof_test_preds = np.zeros(X_test.shape[0])
# OOF 방식으로 모델 훈련 ,검증 , 예측
for idx, (train_idx , valid_idx) in enumerate(folds.split(X,y)):
# 각 폴드를 구분하는 문구 출력
print('#'*40 , f'폴드 {idx+1} / 폴드 {folds.n_splits}' , '#'*40)
X_train , y_train = X[train_idx] , y[train_idx] # 훈련용 데이터
X_valid , y_valid = X[valid_idx] , y[valid_idx] # 검증용 데이터
# LightGBM 전용 데이터셋 생성
dtrain = lgb.Dataset(X_train , y_train) # LightGBM 전용 훈련 데이터셋
dvalid = lgb.Dataset(X_valid , y_valid) # LightGBM 전용 검증 데이터셋
# LightGBM 모델 훈련
lgb_model = lgb.train(params = max_params , # 최적 하이퍼파라미터
train_set = dtrain, # 훈련 데이터 셋
num_boost_round= 2500, # 부스팅 반복 횟수
valid_sets= dvalid , # 성능 평가용 검증 데이터셋
feval = mae_scorer, # 검증용 평가지표
early_stopping_rounds= 300, # 조기종료 조건
verbose_eval = 100) # 100 번째 마다 점수 출력
# 테스트 데이터를 활용해 OOF 예측
oof_test_preds += lgb_model.predict(X_test) / folds.n_splits
# 모델 성능 평가를 위한 검증 데이터 타깃값 예측
oof_val_preds[valid_idx] += lgb_model.predict(X_valid)
oof_test_preds_lgb = oof_test_preds
# 검증 데이터 예측 확률에 대한 정규화 지니계수
Mae_score = mean_absolute_error(y_valid, oof_val_preds[valid_idx])
#gini_score = eval_gini(y_valid, oof_val_preds[valid_idx])
print(f'폴드 {idx+1} MAE SCORE : {Mae_score}\n')
y_preds = oof_test_preds
y_preds
from sklearn.model_selection import train_test_split
num_train = len(train) # 훈련 데이터 개수
# 훈련 데이터와 테스트 데이터 나누기
X= all_data[:num_train] # 0~num_train -1 행
X_test = all_data[num_train:] # num_train ~ 마지막 행
y = train['yield'].values
X_train , X_valid , y_train, y_valid = train_test_split(X,y, test_size = 0.2, random_state=0)
from sklearn.metrics import mean_absolute_error
# 검증 데이터에 대한 예측 수행
y_pred = lgb_model.predict(X_valid)
# MAE 계산
mae = mean_absolute_error(y_valid, y_pred)
print("MAE:", mae)
MAE: 354.75554937001044
==> 성능이 오르진 않네?
==> 베이지안 최적화 진행시 범위를 재지정하는게 좋을거 같다.
==> 1384 / 1875
==> 더 나빠졌네 ㅠ
3. 베이지안 최적화 와 KFOLD 이용한 XGBoost모델 돌리기
def mae_scorer(preds, dtrain):
labels = dtrain.get_label()
return 'Mae' , mean_absolute_error(labels, preds)
from scipy import sparse
from sklearn.model_selection import train_test_split
import xgboost as xgb
num_train = len(train) # 훈련 데이터 개수
# 훈련 데이터와 테스트 데이터 나누기
all_data_sprs = sparse.csr_matrix(all_data)
X= all_data_sprs[:num_train] # 0~num_train -1 행
X_test = all_data_sprs[num_train:] # num_train ~ 마지막 행
y = train['yield'].values
# 8:2 비율로 훈련 데이터, 검증 데이터 분리(베이지안 최적화 수행용)
X_train , X_valid , y_train , y_valid = train_test_split(X,y, test_size=0.2 , random_state=0)
# 베이지안 최적화용 데이터셋
bayes_dtrain = xgb.DMatrix(X_train , y_train)
bayes_dvalid = xgb.DMatrix(X_valid, y_valid)
3-1) 베이진안 최적화를 통한 최적 하이퍼파라미터 찾기
# 베이지안 최적화를 위한 하이퍼파라미터 범위
param_bounds = {'max_depth' : (4 , 10) , # 개별 트리의 최대 깊이, 트리 깊이가 깊을수록 모델이 복잡해지고 과대적합 우려
# 값이 클수록 깊이가 한 단계만 늘어나도 메모리 사용량이 급격히 많아진다.
# 일반적으로 3~10 사이의 값을 주로 사용한다.
'subsample' : (0.5 , 1), # 개별 트리를 훈련할 때 사용할 데이터 샘플링 비율
# 0~1 사이 값으로 설정할 수 있다.
# 0.5 로 설정하면 전체 데이터의 50%를 사용해 트리를 생성
'colsample_bytree' : (0.7 , 1.0), # 개별 트리를 훈련할 때 사용하는 피처 샘플링 비율
# subsample 과 유사한 개념, subsample은 전체 데이터에서 얼마나 샘플링할지 나타내는 비율
# colsample_bytree는 전체 피처에서 얼마나 샘플링할지 나타내는 비율
# 값이 작을수록 과대적합 방지 효과
'min_child_weight' : (5 , 10), # 과대적합 방지위한 값, 값이 클수록 과대적합 방지 효과가 있다.
'gamma' : (8 , 11), # 말단 노드가 분할하기 위한 최소 손실 감소 값
# 소실 감소가 gamma보다 크면 말단 노드를 분할
# 값이 클수록 과대적합 방지 효과가 있다.
'reg_alpha' : (7 , 9) , # L1 규제 조정 값 , 값이 클수록 과대적합 방지 효과
'reg_lambda' : (1.1 , 1.5), # L2 규제 조정값 , 값이 클수록 과대적합 방지 효과
'scale_pos_weight' : (1.4 , 1.6), # 뷸균형 데이터 가중치 조정 값 ,
# 타깃값이 불균형할 때 양성 값에 scale_pos_weight 만큼 가중치를 줘서 균형을 맞춤(타깃값 1을 양성 값으로 간주)
# 일반적으로 scale_pos_weight 값을 (음성 타깃값 개수 / 양성 타깃값 개수) 로 설정
'learning_rate' : (0.02, 0.1)} # 학습률( 부스팅 스텝을 반복하면서 모델을 업데이트하는 데 사용되는 비율)
# 값이 고정된 하이퍼파라미터
fixed_params = {'objective' : 'reg:squarederror' ,# 훈련 목적 , binary : logistic( 확률값을 구하는 이진분류)
# reg : squarederror (회귀 문제)
# 소프트맥스 함수를 사용하는 다중분류에서는 multi : softmax 사용
# 확률값을 구하는 다중분류에서는 'multi : softprob' 사용
'random_state' : 1991} # 랜덤 시드값(코드를 반복 실행해도 같은 결과가 나오게 지정하는 값)
# ======================================================
def eval_function(max_depth ,learning_rate, subsample , colsample_bytree , min_child_weight , reg_alpha , gamma , reg_lambda , scale_pos_weight) :
# 최적화하려는 평가지표(지니계수) 계산 함수
# 베이지안 최적화를 수행할 하이퍼파라미터
params = {'max_depth' : int(round(max_depth)) , # 개별 트리의 최대깊이
'learning_rate' : learning_rate,
'subsample' : subsample, # 개별 트리를 훈련할 때 사용할 데이터 샘플링 비율
'colsample_bytree' : colsample_bytree , # 개별 트리를 훈련할때 사용하는 피처 샘플링
'min_child_weight' : # 과대적합 방지위한 값
min_child_weight,
'gamma' : gamma, # 말단 노드가 분할하기 위한 최소 손실 감소 값
'reg_alpha' : reg_alpha, # L1 규제 조정값
'reg_lambda' : reg_lambda, # L2 규제 조정값
'scale_pos_weight' : scale_pos_weight} # 불균형 데이터 가중치 조정값
# 값이 고정된 하이퍼파라미터도 추가
params.update(fixed_params)
print('하이퍼파라미터 : ' , params)
# XGBoost 모델 훈련 , train() 메서드의 하이퍼파라미터
xgb_model = xgb.train(params = params , # XGBoost 모델의 하이퍼파라미터 목록 , 딕셔너리 타입으로 전달
dtrain = bayes_dtrain, # 훈련 데이터셋, xgboost.DMatrix 타입으로 전달
num_boost_round= 2000, # 부스팅 반복 횟수, 정수형 타입으로 전달
# num_boost_round 값이 클수록 성능이 좋아질 수 있으나 과대적합의 우려가 있다.
# num_boost_round 값이 작으면 반복 횟수가 줄어들어 훈련 시간이 짧아진다.
# 일반적으로 num_boost_round를 늘리면 learning_rate를 줄여야 한다.
evals = [(bayes_dvalid , ' bayes_dvalid')],
# 모델 성능 평가용 검증 데이터셋
# (DMatrix, 문자열) 쌍들을 원소로 갖는 리스트 타입으로 전달, 검증 데이터셋 이름을 원하는 대로 문자열로 정하면 된다.
maximize = True, # feval 평가지수가 높으면 좋은지 여부
feval = mae_scorer, # 검증용 평가지표, 사용자 정의 함수 형태
# evals를 활용해 모델 성능을 검증할 때 사용할 사용자 정의 평가지표 함수
# 예측값과 실제값을 파라미터로 전달받아, 평가지표명과 평가점수를 반환하는 함수이다.
early_stopping_rounds= 200,
# 조기종료 조건
# 모델은 기본적으로 num_boost_round만큼 훈련을 반복하며, 매 이터레이션마다 evals로 모델 성능을 평가하여 성능이 연속으로
# 좋아지지 않는다면 훈련을 중단하는데, 훈련 중단에 필요한 최소횟수가 early_stopping_rounds 이다. 즉 , early_stopping_rounds
# 동안 모델 성능이 좋아지지 않는다면 훈련을 중단한다.
# 과대적합 방지 효과
# 조기종료를 적용하기 위해서는 evals 에 검증 데이터가 하나 이상 있어야한다. 또한 evals에 검증 데이터가 여러 개라면 마지막 검증
# 데이터를 기준으로 조기종료 조건을 적용한다.
verbose_eval= False) # 성능 점수 로그 설정 값
# True 로 설정하면 매 부스팅 스텝마다 평가점수르 출력
# 출력값이 너무 많아지는 것을 방지하기위해 verbose_eval로 설정
best_iter = xgb_model.best_iteration # 최적 반복횟수
# 검증 데이터로 예측 수행
preds = xgb_model.predict(bayes_dvalid , iteration_range=(0, best_iter))
# 지니계수 계산
mae_score = mean_absolute_error(y_valid, preds)
print(f'Mae_score : {mae_score}\n')
return -mae_score
%%time
from bayes_opt import BayesianOptimization
# 베이지안 최적화 객체 생성
optimizer = BayesianOptimization(f= eval_function, pbounds = param_bounds , random_state= 0)
# 베이지안 최적화 수행
optimizer.maximize(init_points= 3 , n_iter= 6)
# 평가함수 점수가 최대일 대 하이퍼파라미터
max_params = optimizer.max['params']
max_params
#%%
max_params['max_depth'] = int(round(max_params['max_depth']))
max_params.update(fixed_params)
max_params
3-2) KFOLD를 통한 검증을 해서 제일 좋은 훈련(mae값 좋은거) 찾기
from sklearn.model_selection import StratifiedKFold, KFold
# 층화 K 폴드 교차 검증기 생성
folds = KFold(n_splits= 5 , shuffle= True , random_state= 1991)
# OOF 방식으로 훈련된 모델로 검증 데이터 타깃값을 예측한 확률을 담을 1차원 배열
oof_val_preds = np.zeros(X.shape[0])
# # OOF 방식으로 훈련된 모델로 테스트 데이터 타깃값을 예측한 확률을 담을 1차원 배열
oof_test_preds = np.zeros(X_test.shape[0])
# OOF 방식으로 훈련된 모델 훈련 , 검증 , 예측
for idx , (train_idx , valid_idx) in enumerate(folds.split(X,y)):
# 각 폴드를 구분하는 문구 출력
print('#' *40, f'폴드 {idx+1} / 폴드 {folds.n_splits}' , '#'*40)
# 훈련용 데이터, 검증용 데이터 설정
X_train , y_train = X[train_idx] , y[train_idx]
X_valid , y_valid = X[valid_idx] , y[valid_idx]
#XGBoost 전용 데이터셋 생성
dtrain = xgb.DMatrix(X_train , y_train)
dvalid = xgb.DMatrix(X_valid , y_valid)
dtest = xgb.DMatrix(X_test)
#XGBoost 모델 훈련
xgb_model = xgb.train(params = max_params,
dtrain = dtrain,
num_boost_round = 2000,
evals = [(dvalid , 'valid')],
maximize = True,
feval = mae_scorer,
early_stopping_rounds = 200,
verbose_eval = 100)
# 모델 성능이 가장 좋을 때의 부스팅 반복 횟수 저장
best_iter= xgb_model.best_iteration
# 테스트 데이터를 활용해 OOF 예측
oof_test_preds += xgb_model.predict(dtest, iteration_range = (0 , best_iter))/ folds.n_splits
oof_test_preds_xgb = oof_test_preds
# 모델 성능 평가를 위한 검증 데이터 타깃값 예측
oof_val_preds[valid_idx] += xgb_model.predict(dvalid , iteration_range=(0, best_iter))
# 검증 데이터 예측 확률에 대한 정규화 지니계수
mae_score = mean_absolute_error(y_valid , oof_val_preds[valid_idx])
print(f'폴드 {idx+1} MAE : {mae_score}\n')
y_preds = oof_test_preds
y_preds
from sklearn.model_selection import train_test_split
num_train = len(train) # 훈련 데이터 개수
# 훈련 데이터와 테스트 데이터 나누기
X = all_data[:num_train] # 0~num_train -1 행
X_test = all_data[num_train:] # num_train ~ 마지막 행
y = train['yield'].values
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=0)
from sklearn.metrics import mean_absolute_error
dvalid = xgb.DMatrix(X_valid)
y_pred = xgb_model.predict(dvalid)
# MAE 계산
mae = mean_absolute_error(y_valid, y_pred)
print("MAE:", mae)
==> MAE: 315.97711915608136
==> 343.6285 최고점!!
==> 984 / 1875
==> 내가 한것중 최고!