241023 TIL #522 AI Tech #55 optuna로 하이퍼파라미터 조정

김춘복·2024년 10월 23일
0

TIL : Today I Learned

목록 보기
524/575

Today I Learned

오늘은 최종 제출 하루 전이라서 모델 세팅에 몰두했다.


Optuna로 하이퍼파라미터 조정

  • LightGBM에 하이퍼 파라미터 조정을 위해 Optuna를 적용해봤다.

  • def objective 함수를 만들어 각 파라미터의 low와 high값을 설정해두고 가장 fold_mae의 합이 최소가 되는 파라미터 값을 찾는다. n_trials를 num_boost_round와 적절하게 세팅한 후 진행한다.

  • 마지막 최종 예측은 best_params로 진행해서 최종적으로 구한다.

  • 코드

import lightgbm as lgb
import numpy as np
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
import optuna

# 학습에 사용할 특징 열
feature_columns = [col for col in temp_train_df.columns if col not in ['deposit', '_type', 'index']]

# 학습 데이터 준비
X = temp_train_df[feature_columns]
y = temp_train_df['deposit']


# 5-fold 교차 검증 설정
n_folds = 5
kf = KFold(n_splits=n_folds, shuffle=True, random_state=42)

def objective(trial):
    # 하이퍼파라미터 탐색 공간 정의
    params = {
        'objective': 'regression',
        'metric': 'mae',
        'boosting_type': 'gbdt',
        'num_leaves': trial.suggest_int('num_leaves', 21, 51),
        'learning_rate': trial.suggest_float('learning_rate', 0.05, 0.05),
        'feature_fraction': trial.suggest_float('feature_fraction', 0.8, 1.0),
        'bagging_fraction': trial.suggest_float('bagging_fraction', 0.8, 1.0),
        'bagging_freq': trial.suggest_int('bagging_freq', 3, 10),
        'min_child_samples': trial.suggest_int('min_child_samples', 10, 100),
        'max_depth': trial.suggest_int('max_depth', 5, 50),
        'seed': 42,
    }
    
    # 교차 검증 결과를 저장할 변수
    cv_scores = []
    
    for fold, (train_idx, val_idx) in enumerate(kf.split(X), 1):
        X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
        y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
        
        dtrain = lgb.Dataset(X_train, label=y_train)
        dval = lgb.Dataset(X_val, label=y_val, reference=dtrain)
        
        model = lgb.train(
            params,
            dtrain,
            num_boost_round=500,
            valid_sets=[dval],
        )
        
        val_pred = model.predict(X_val)
        fold_mae = mean_absolute_error(y_val, val_pred)
        cv_scores.append(fold_mae)
    
    return np.mean(cv_scores)

study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=50)

# 최적의 하이퍼파라미터 출력
print("Best parameters:", study.best_params)
print("Best MAE:", study.best_value)

# 최적화된 파라미터로 최종 모델 학습
best_params = study.best_params
best_params.update({
    'objective': 'regression',
    'metric': 'mae',
    'boosting_type': 'gbdt',
    'seed': 42
})

# 최종 예측은 기존 코드와 동일한 방식으로 진행
oof_predictions = np.zeros(len(X))
test_predictions = np.zeros(len(test_df))

def print_evaluation(period=10):
    def callback(env):
        if (env.iteration + 1) % period == 0:
            train_mae = env.evaluation_result_list[0][2]
            val_mae = env.evaluation_result_list[1][2]
            print(f"[{env.iteration + 1}] Train MAE: {train_mae:.4f}, Val MAE: {val_mae:.4f}")
    return callback

for fold, (train_idx, val_idx) in enumerate(kf.split(X), 1):
    X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
    y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
    
    dtrain = lgb.Dataset(X_train, label=y_train)
    dval = lgb.Dataset(X_val, label=y_val, reference=dtrain)
    
    model = lgb.train(
        best_params,
        dtrain,
        num_boost_round=12000,
        valid_sets=[dtrain, dval],
        callbacks=[print_evaluation(100)]
    )
    
    oof_predictions[val_idx] = model.predict(X_val)
    test_predictions += model.predict(test_df[feature_columns]) / n_folds
profile
Backend Dev / Data Engineer

0개의 댓글