[PYTHON - 머신러닝_캐글_실습-03]안전 운전자 예측 모델링★LightGBM 모델★최적의하이퍼파라미터찾기★베이지안 최적화
7. 성능개선 1 : LightGBM 모델
def eval_function(num_leaves , lambda_l1 , lambda_l2 , feature_fraction , bagging_fraction , min_child_samples , min_child_weight) :
# 최적화하려는 평가지표(지니계수) 계산 함수
# 베이지안 최적화를 수행할 하이퍼파라미터
params = {'num_leaves' : int(round(num_leaves)) , # 개발 트리가 가질 수 있는 최대 말단 노드 개수, 트리 복잡도 결정 , 값이 클수록 좋다.
'lambda_l1' : lambda_l1, # L1 규제 조정값 , 값이 클 수록 과대적합 방지 효과
'lambda_l2' : lambda_l2 , # 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} #
#하이퍼파라미터도 추가
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 = gini, # 검증용 평가지표
early_stopping_rounds= 300, # 조기종료 조건
verbose_eval= False) # 계속 점수 출력
# 검증 데이터로 예측 수행
preds = lgb_model.predict(X_valid)
# 지니계수 계산
gini_score = eval_gini(y_valid, preds)
print(f'지니계수 : {gini_score}\n')
return gini_score
=====================
# 베이지안 최적화를 수행할 하이퍼파라미터
params = {'num_leaves' : int(round(num_leaves)) , # 개발 트리가 가질 수 있는 최대 말단 노드 개수, 트리 복잡도 결정 , 값이 클수록 좋다.
'lambda_l1' : lambda_l1, # L1 규제 조정값 , 값이 클 수록 과대적합 방지 효과
'lambda_l2' : lambda_l2 , # 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} #
==> 최적화할 하이퍼파라미터 정의 : 인수로 받은 하이퍼파라미터의 값(범위)를 그대로 대입한다.
==> num_leaves 와 min_child_samples는 정수여야 한다. ==> 베이지안 최적화를 수행하면 하이퍼파라미터 지정 범위 내 실숫값을 탐색하기 때문에 eval_function()에 인수로 전달되는 값도 모두 실수형이 된다.
#하이퍼파라미터도 추가
params.update(fixed_params)
print('하이퍼파라미터 : ' , params)
==> params 는 딕셔너리 타입이기 때문에 update() 함수로 원소(fixed_params)를 추가한다.
# LightGBM 모델 훈련
lgb_model = lgb.train(params = params , # 훈련용 하이퍼파라미터
train_set = bayes_dtrain, # 훈련 데이터셋
num_boost_round= 2500, #부스팅 반복횟수
valid_sets= bayes_dvalid, # 성능 평가용 검증 데이터 셋
feval = gini, # 검증용 평가지표
early_stopping_rounds= 300, # 조기종료 조건
verbose_eval= False) # 계속 점수 출력
# 검증 데이터로 예측 수행
preds = lgb_model.predict(X_valid)
==> 앞에서 지정하 하이퍼파라미터를 이용하여 LightGBM 모델을 훈련한 뒤 검증 데이터로 예측을 수행한다.
# 지니계수 계산
gini_score = eval_gini(y_valid, preds)
print(f'지니계수 : {gini_score}\n')
return gini_score
==> 예측 확률값(preds)과 검증 데이터의 실제 타깃값(y_valid)을 이용해 지니계수를 계산한다.'
8. 성능개선 1 : LightGBM 모델_베이지안 최적화 실행
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 는 베이지안 최적화 반복횟수
==> 베이지안 최적화 수행
==> 모델 훈련을 총 9번 반복하여 베이지안 최적화가 진행된다.
| iter | target | baggin... | featur... | lambda_l1 | lambda_l2 | min_ch... | min_ch... | num_le... |
# 평가함수 점수가 최대일 대 하이퍼파라미터
max_params = optimizer.max['params']
max_params
# 값이 고정된 하이퍼파라미터 추가
max_params.update(fixed_params)
9. 최적 하이퍼파라미터를 통한 모델 훈련 및 성능 검증
from sklearn.model_selection import StratifiedKFold
# 층화 K 폴드 교차 검증기 생성
folds = StratifiedKFold(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 , 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 = gini, # 검증용 평가지표
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
# 검증 데이터 예측 확률에 대한 정규화 지니계수
gini_score = eval_gini(y_valid, oof_val_preds[valid_idx])
print(f'폴드 {idx+1} 지니계수 : {gini_score}\n')
==> lgb_model = lgb.train(params = max_params) 로 변경
https://knowallworld.tistory.com/397
print('OOF 검증 데이터 지니계수 :' , eval_gini(y, oof_val_preds))
==> 검증 데이터로 예측한 확률과 실제 타깃값의 지니계수