Optuna로 하이퍼파라미터 튜닝하기

최하린·2023년 5월 18일
0

하이퍼파라미터 튜닝 방법으로 optuna라는 새로운 방법을 알게 되어 정리해보려고 한다.

optuna란?

Optuna란 하이퍼파라미터 최적화를 자동화해주는 프레임워크이다.

Optuna는 최적화할 함수인 Objective Function을 정의하여 하이퍼파라미터 조합을 입력으로 받고, 해당 조합의 성능을 평가하여 반환하며, Objective Function에는 최대화 또는 최소화할 성능 지표가 있어야 한다.

또한, Optuna는 하이퍼파라미터 튜닝 과정을 관리하기 위해 Study라는 객체를 사용하는데 Study는 여러 개의 Trial을 생성하고 관리하며, 최적의 조합을 탐색한다. Optuna는 Study를 통해 다양한 알고리즘을 사용하여 효율적인 하이퍼파라미터 탐색을 수행한다.

Optuna에는 다음과 같은 장점이 있다.

  • 넓은 범용성: 머신러닝 및 딥러닝 라이브러리와의 통합을 지원하여 TensorFlow, PyTorch, XGBoost, LightGBM 등과 같은 다양한 라이브러리와 함께 사용할 수 있다.
  • 간단하고 빠르다: Optuna는 사용하기 쉽고 직관적인 API를 제공하여 하이퍼파라미터 튜닝 작업을 간편하게 수행할 수 있다.
  • 자동 중단 기능: Optuna는 Pruning 기능을 제공하여 비효율적인 시도를 조기에 중단할 수 있으며, 이를 통해 시간과 자원을 절약할 수 있다.
  • 쉬운 시각화: feature importance, Contour Visualization, Parallel Coordinate Visualization 등 다양한 시각화 기능을 제공한다.

캐글 데이터에 rf 모델과 optuna를 사용하여 하이퍼파라미터를 튜닝해보았다.

  1. 라이브러리 및 데이터 import
import pandas as pd
import numpy as np
import koreanize_matplotlib
import lightgbm as lgb
from sklearn.ensemble import RandomForestRegressor
import optuna
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_log_error, r2_score, mean_squared_error

df_onehot = pd.read_csv('train_onehot.csv', index_col='날짜')
df_onehot.head()
  1. train, test 데이터 분리
feature_names = df_onehot.columns.to_list()
feature_names.remove('판매량')

label_name = '판매량'

X = df_onehot[feature_names]
y = df_onehot[label_name]

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42)

X_train.shape, X_valid.shape, y_train.shape, y_valid.shape
  1. 목적 함수 정의
# 목적 함수 정의
def objective(trial):
    # 하이퍼파라미터 탐색 공간 정의
    n_estimators = trial.suggest_int('n_estimators', 100, 1000, step=100)
    max_depth = trial.suggest_int('max_depth', 5, 15)
    min_samples_split = trial.suggest_int('min_samples_split', 2, 10)
    min_samples_leaf = trial.suggest_int('min_samples_leaf', 1, 10)
    max_features = trial.suggest_categorical('max_features', ['auto', 'sqrt'])
    
    # Random Forest 모델 생성
    model = RandomForestRegressor(
        n_estimators=n_estimators,
        max_depth=max_depth,
        min_samples_split=min_samples_split,
        min_samples_leaf=min_samples_leaf,
        max_features=max_features,
        random_state=42
    )
    
    # 모델 학습
    model.fit(X_train, y_train)
    
    # 검증 데이터에 대한 예측
    y_valid_pred = model.predict(X_valid)
    
    # 검증 데이터에 대한 정확도 계산
    r2 = r2_score(y_valid, y_valid_pred)
    
    return r2
  1. Study 객체 생성
study = optuna.create_study(direction='maximize') # r2 score를 최대화하므로 'maximize'로 설정
study.optimize(objective, n_trials=100)

best_params = study.best_params
best_score = study.best_value
print('Best Parameters:', best_params)
print('Best r2 score:', best_score)
  1. best parameter 저장 및 학습
best_model = RandomForestRegressor(
    n_estimators=best_params['n_estimators'],
    max_depth=best_params['max_depth'],
    min_samples_split=best_params['min_samples_split'],
    min_samples_leaf=best_params['min_samples_leaf'],
    max_features=best_params['max_features'],
    random_state=42
)
best_model.fit(X_train, y_train)
  1. valid 데이터셋 예측 및 평가
y_valid_pred = best_model.predict(X_valid)

print('rmsle:', np.sqrt(mean_squared_log_error(y_valid, y_valid_pred)))
print('r2:', r2_score(y_valid, y_valid_pred))

결과:
rmsle: 0.19742834345385674
r2: 0.7247682186150417

optuna를 사용해보니 데이터의 크기가 큼에도 불구하고 간편하고 빠른 것 같다. 아마 모델을 변경하면 더 좋은 스코어를 얻을 수 있지 않을까 싶다. grid search나 random search보다 앞으로 더 자주 사용하게 될 것 같다.

0개의 댓글