Bayesian Optimization 을 이용한 LightGBM 파라미터 튜닝 실습

박경민·2023년 2월 27일
0

[Projects]

목록 보기
9/12
post-custom-banner

이전 데이터는 함수 형태로 모두 가져와준다. 다음은 Bayesian Optimization 을 이용한 코드만 후술할 것이다.

Bayesian Optimization

# bayesian optimization 패키지 설치
!pip install bayesian-optimization

from bayes_opt import BayesianOptimization
from sklearn.metrics import roc_auc_score
from lightgbm import LGBMClassifier

함수의 입력값 search범위를 설정

bayesian_params = {
    'max_depth':(6, 16), #트리 최대 깊이
    'num_leaves':(24,64), #트리 하나에 최대 잎 개수
    'min_child_samples': (10, 200), #하나의 잎에 최소 데이터 개수 (오버피팅 대응)
    'min_child_weight': (1, 50), #하나의 잎에 최소 sum hessian
    'subsample': (0.5, 1), #
    'colsample_bytree': (0.5, 1), #피처의 50% 를 트레이닝 전에 선택
    'max_bin': (10, 500), #bins 의 최대 개수
    'reg_lambda': (0.001, 10), #L2 regularization
    'reg_alpha': (0.01, 50) #L1 regularization 
}
}

파라미터의 숫자는 파라미터를 많이 쳐봄으로서 경험적으로 아는 수밖에 없다. 사이트 에 파라미터에 대한 정의와 설명이 모두 담겨있으니 참조하도록 하자. 일단 나와있는 것은 모두 주석으로 작성해놨다.

최대 값을 구할 함수 선언

이 함수는 하나의 반복마다 하이퍼파라미터를 입력받아 분류 학습하고 roc_auc 를 반환하는 함수이다.

def lgb_roc_eval(max_depth, num_leaves, min_child_samples, min_child_weight, subsample, colsample_bytree, max_bin, reg_lambda, reg_alpha):
  params = {
      "n_estimators" : 500, "learning_rate": 0.02,
      'max_depth': int(round(max_depth)),
      'num_leaves': int(round(num_leaves)),
      'min_child_samples': int(round(min_child_samples)),
      'min_child_weight': int(round(min_child_weight)),
      'subsample': max(min(subsample, 1), 0), # 0 과 1 사이
      'colsample_bytree': max(min(colsample_bytree, 1), 0),
      'max_bin':  max(int(round(max_bin)),10),
      'reg_lambda': max(reg_lambda,0),
      'reg_alpha': max(reg_alpha, 0)

  }
  lgb_model = LGBMClassifier(**params)
  lgb_model.fit(train_x, train_y, eval_set=[(train_x, train_y), (valid_x, valid_y)], eval_metric= 'auc', verbose= 100, 
                early_stopping_rounds= 100)
  valid_proba = lgb_model.predict_proba(valid_x)[:, 1]
  roc_auc = roc_auc_score(valid_y, valid_proba)

  return roc_auc

실제로 학습을 할 때에는 int(round()) 를 통해 정수값으로 입력받을 수 있도록 해준다.

BayesianOptimization 객체 생성 후 함수 반환값이 최대가 되는 입력값 search 를 위한 iteration 수행

반환값 roc_auc 를 최대화하는 것이 현재의 목표다. 객체를 생성하고 init_points 와 n_iter 로 반복수를 지정해주면 최대화를 위해 객체가 달린다!

lgbBO = BayesianOptimization(f= lgb_roc_eval, pbounds=bayesian_params, random_state = 0)
lgbBO.maximize(init_points = 5, n_iter = 25)

🤔 장장 1시간 30분이 넘어가는 파라미터 튜닝 시간이 걸렸다...

Iteration 수행 결과 출력

.res 는 하나의 반복을 돌 때마다 그때의 반환값과 파라미터 결과값을 기억하고 있다.

lgbBO.res

Iteration 결과 Dictionary 에서 최대 target 을 가지는 index 추출하고 그때의 parameter 추출

# dictionary에 있는 target값을 모두 추출
target_list = []
for result in lgbBO.res:
    target = result['target']
    target_list.append(target)
print(target_list)
# 가장 큰 target 값을 가지는 순번(index)를 추출
print('maximum target index:', np.argmax(np.array(target_list)))

# 가장 큰 target값을 가지는 index값을 기준으로 res에서 해당 parameter 추출. 
max_dict = lgbBO.res[np.argmax(np.array(target_list))]
print(max_dict)

.res 로 반환값과 파라미터를 돌면서 target 값을 가져온다. 그 중 target 값이 가장 큰 index 를 추출한다. 이를 출력을 해주면 된다. index 는 np.argmax(np.array(target_list))로 가져오면 된다.

def train_apps_all(apps_all_train):
    ftr_app = apps_all_train.drop(['SK_ID_CURR', 'TARGET'], axis=1)
    target_app = apps_all_train['TARGET']

    train_x, valid_x, train_y, valid_y = train_test_split(ftr_app, target_app, test_size=0.3, random_state=2020)
    print('train shape:', train_x.shape, 'valid shape:', valid_x.shape)
    clf = LGBMClassifier(
                nthread=4,
                n_estimators=1000,
                learning_rate=0.02,
                max_depth = 13,
                num_leaves=57,
                colsample_bytree=0.638,
                subsample=0.682,
                max_bin=435,
                reg_alpha=0.936,
                reg_lambda=4.533,
                min_child_weight=25,
                min_child_samples=166,
                silent=-1,
                verbose=-1,
                )

    clf.fit(train_x, train_y, eval_set=[(train_x, train_y), (valid_x, valid_y)], eval_metric= 'auc', verbose= 100, 
                early_stopping_rounds= 100)
    
    return clf

#모델 학습 
apps_all = get_apps_all_with_prev_agg(apps, prev)
apps_all = get_apps_all_encoded(apps_all)
apps_all_train, apps_all_test = get_apps_all_train_test(apps_all)
clf = train_apps_all(apps_all_train)

#예측, 파일 생성. 
preds = clf.predict_proba(apps_all_test.drop('SK_ID_CURR', axis=1))[:, 1 ]
apps_all_test['TARGET'] = preds
apps_all_test[['SK_ID_CURR', 'TARGET']].to_csv('prev_baseline_tuning_01.csv', index=False)

profile
Mathematics, Algorithm, and IDEA for AI research🦖
post-custom-banner

0개의 댓글