하이퍼파라미터 튜닝 방법으로 optuna라는 새로운 방법을 알게 되어 정리해보려고 한다.
Optuna란 하이퍼파라미터 최적화를 자동화해주는 프레임워크이다.
Optuna는 최적화할 함수인 Objective Function을 정의하여 하이퍼파라미터 조합을 입력으로 받고, 해당 조합의 성능을 평가하여 반환하며, Objective Function에는 최대화 또는 최소화할 성능 지표가 있어야 한다.
또한, Optuna는 하이퍼파라미터 튜닝 과정을 관리하기 위해 Study라는 객체를 사용하는데 Study는 여러 개의 Trial을 생성하고 관리하며, 최적의 조합을 탐색한다. Optuna는 Study를 통해 다양한 알고리즘을 사용하여 효율적인 하이퍼파라미터 탐색을 수행한다.
Optuna에는 다음과 같은 장점이 있다.
캐글 데이터에 rf 모델과 optuna를 사용하여 하이퍼파라미터를 튜닝해보았다.
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()
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
# 목적 함수 정의
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
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)
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)
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보다 앞으로 더 자주 사용하게 될 것 같다.