본문 바로가기
Kaggle 대회

[ASHRAE - Great Energy Predictor III] Hyperparameter Optimaization

by 사자처럼 우아하게 2019. 12. 14.

 

이번 포스팅에서는 Hyperparameter Tuning을 통한 LB Score를 향상시키는 방법에 대해 알아보겠습니다.

제가 사용하는 Hyperparameter 를 찾아가는 방법은 세가지 입니다.

  - Grid Search , Random Search, Bayesian Optimization Functions


Grid Search는 Parameter 별로 값을 지정해주고 이를 조합하여 최적의 조합을 찾아가는 방식이고

Random Search는 Parameter 별로 범위를 지정해주고 그 안에서 Random 하게 값을 뽑아서 조합하는 방식입니다.

일정 시간 안에 결과를 내야하는 경우에는, Grid Search < Random Search 가 더 좋은 결과를 내는 경향이 있다고

알려져 있습니다만, 둘다 이전 Search 결과를 다음 Searching에 반영하지 못하여 Cost만 높인다는 단점이 있습니다.

 

[Bergstra and Bengio(2012)]

Baysian Optimization Function 은 Grid/Random Search과 다르게 사전지식(Prior Knowledge)을 찾는 과정에서 활용하

는 것으로 초기에 Random하게 Search를 진행하고 이를 바탕으로 통계적인 함수를 구축하고 이에 의해 가장 가능성이

있는 지점의 Parameter를 찾아 최적값을 찾아갑니다. 자세한 내용은 링크를 확인하시면 됩니다. (링크 바로가기)

 

이번 대회에서는 Baysian Optimization Function을 활용하여 Hyperparameter Optimization을 실시하였는데, 

총 20번의 Search 하는데 LGBM은 30시간, XGBOOST_GPU는 20시간 정도 소요되었습니다.(16 Tread, Ram 64 GB)

(깃헙 바로가기 : LGBM , XGBOOST)

 

%%time
import lightgbm as lgb
import xgboost as xgb
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_log_error
from bayes_opt import BayesianOptimization
import pickle
folds = 3
seed = 99 #666

# Hyperparameter range
params_range = {
                'learning_rate' : (.01,.07),
                'max_depth' : (8,13),
                'subsample' : (0.7,0.9),
                'colsample_bytree' : (0.7,0.8),
                'reg_alpha' :( 0.1,0.4),
                'reg_lambda' : (0.5,0.85),
                
               }

%%time
paramlst = []
scorelst =[]

def running(learning_rate, max_depth, subsample, colsample_bytree, reg_alpha, reg_lambda):
    params = {
    'objective': 'reg:squarederror',
    'tree_method': 'gpu_hist',
    "learning_rate": learning_rate,
    "max_depth" : int(round(max_depth)),
    "subsample": max(min(subsample,1),0),    
    "colsample_bytree": max(min(colsample_bytree,1),0),
    "reg_alpha": max(min(reg_alpha,1),0),
    "reg_lambda": max(min(reg_lambda,1),0),
    "n_jobs" : 4,
    "missing" : -999
    }
    
    print(params)
    kf = KFold(n_splits=folds, shuffle=False, random_state=seed)
    scores = [] 
    models = []
    for i,(train_index, val_index) in enumerate(kf.split(train_df)):
        train_X = train_df.iloc[train_index]
    
        val_X = train_df.iloc[val_index]
        train_y = target.iloc[train_index]
        val_y = target.iloc[val_index]
        xgb_train = xgb.DMatrix(train_X, train_y)
        xgb_eval = xgb.DMatrix(val_X, val_y)
        gbm = xgb.train(params, xgb_train, num_boost_round = 3000,evals=[(xgb_train, 'train'), (xgb_eval, 'val')],
                    verbose_eval = 30 , early_stopping_rounds = 30)
        pickle.dump(gbm,open('xgb_opti_%s.pickle'%i, "wb") )
        gbm.__del__() 
        del xgb_train, xgb_eval
        gc.collect()
    for f in range(folds):
        models.append(pickle.load(open("xgb_opti_%s.pickle"%f, "rb")))
    
    ii = 0
    res3 = []
    step_size = 50000
        
    for j in tqdm(range(int(np.ceil(test_df.shape[0] / 50000)))):
        res3.append([np.expm1(model.predict(xgb.DMatrix(test_df.iloc[ii:ii + step_size]))) for model in models])
#         res3.append([np.expm1(model.predict(test_df.iloc[i:i + step_size])) for model in models])
        ii += step_size
        
    res4 = []
    print(len(res3))
    for k in range(len(res3)):
        res4.append((0.6*res3[k][0]+0.3*res3[k][1]+0.1*res3[k][2]))
#         if i==100 : break
    
    
    res4 = np.concatenate(res4)
    sample_submission = pd.read_csv('sample_submission.csv')
    sample_submission["meter_reading"] = res4
    sample_submission.loc[sample_submission['meter_reading'] < 0, 'meter_reading'] = 0

    sample_submission = pd.merge(sample_submission,leak_df.loc[:,['row_id','leak_meter_reading']],how ='inner')    
    score = np.sqrt(mean_squared_log_error( sample_submission['leak_meter_reading'], sample_submission['meter_reading'] ))
    print(score)
    scorelst.append(score)
    paramlst.append(params)
    
    df_para = pd.DataFrame({"parameter" : paramlst,"score": scorelst})
    df_para.to_csv('para_xgb.csv',index=False)
    
    return -np.sqrt(mean_squared_log_error( sample_submission['leak_meter_reading'], sample_submission['meter_reading'] ))        

    
Baysian = BayesianOptimization(running, params_range,random_state = seed)
Baysian.maximize(init_points = 3, n_iter = 20)

 

 

* Reference 

   - https://www.kaggle.com/aitude/ashrae-hyperparameter-tuning

   - http://research.sualab.com/introduction/practice/2019/02/19/bayesian-optimization-overview-1.html

   - https://databuzz-team.github.io/2018/12/05/hyperparameter-setting/

 

 

 

댓글