[ML] Bayesian Optimization 기반의 HyperOpt

조치연·2025년 3월 30일

ML

목록 보기
8/17
post-thumbnail

기존에 모델의 하이퍼 파라미터 튜닝을 위해서 사잇킷런에서 제공하는 Grid Search 방식을 이용했습니다.

Grid Search 방식은 정해준 모든 하이퍼 파라미터 값을 적용하기 때문에 최적의 값을 구해준다는 장점이 있지만, 튜닝해야 할 하이퍼 파라미터 개수가 많을 경우 수행 시간이 오래 걸립니다.

이전 [ML] XGBoost / LightGBM에서도 봤다시피 성능이 뛰어난 XGBoost와 LightGBM은 성능이 뛰어난 알고리즘 이지만, 파라미터 수가 많습니다.

이런 경우, 우리는 베이지안 최적화 기법을 사용할 수 있습니다.

이 장에서는 베이지안 최적화의 수학적 기교(?)를 공부하는 것이 아닙니다. 활용에 초점을 맞췄습니다.😁


📚 Bayesian Optimization(베이지안 최적화)

베이지안 최적화는 목적 함수 식을 제대로 알 수 없는 블랙 박스 형태의 함수에서 최대 또는 최소 함수 반환 값을 만드는 최적 입력값을 가능한 적은 시도를 통해 빠르고 효과적으로 찾아주는 방식입니다.


✅ Bayesian Probability(베이지안 확률)

베이지안 최적화는 베이지안 확률에 기반을 두고 있는 최적화 기법입니다.

베이지안 확률은 베이즈 정리(Bayes' theorem)라 불리며, 종속적(의존적) 관계에 놓인 사건들을 기반으로 확률을 구합니다. 즉, '두 확률 변수의 사전 확률과 사후 확률을 나타내는 정리' 입니다.

아래는 사전 확률을 통해 사후 확률을 예측하는 베이지안 확률 식입니다.



✅ Surrogate Model / Acquisition Function(대체 모델 / 획득 함수)

베이지안 최적화를 구성하는 두 가지 중요 요소는 대체 모델과 획득 함수 입니다.

대체 모델은 획득 함수로부터 최적 함수를 예측할 수 있는 입력값을 받아 이를 기반으로 최적 함수 모델을 예측합니다.
획득 함수는 개선된 대체 모델을 기반으로 최적 입력값을 계산합니다.

대체 모델은 주어진 입력값을 통해 예측 최적함수를 찾는다는 점이 핵심입니다.


대체 모델은 최적 함수를 추정할 때, 다양한 알고리즘을 사용할 수 있는데 일반적으로는 Gaussian Process(가우시안 프로세스)를 사용합니다.

베이지안 확률은 대체 모델을 생성할 때 사용됩니다.


✅ HyperOpt

베이지안 최적화를 머신러닝 모델에 적용할 수 있는 파이썬 패키지들이 많습니다.
대표적으로 HyperOpt, Bayesian Optimization, Optuna 등이 있습니다.

HyperOpt의 주요 로직은 다음과 같습니다.

  • Search Space(검색 공간)
  • Objective Function(목적 함수)
  • 목적 함수의 최솟값을 가지는 파라미터 유추

각 로직을 코드로 표현하면 다음과 같습니다.

from hyperopt import hp

# search space 생성.
params = {'x': hp.quniform('x', 1, 15, 1), 'y': hp.uniform('y', 0.1, 1)}
from hyperopt import STATUS_OK

# Objective Function 생성.
def objective_function(params):
    x = params['x']
    y = params['y']

    return x ** 2 - y
from hyperopt import fmin, tpe, Trials

# 유추
trial_val = Trials()
best_param = fmin(fn=objective_function, space=params, algo=tpe.suggest, max_evals=5, trials=trial_val)



✔ Search Space

Search Space는 parameter의 범위를 나타냅니다.
GrideSearch 방법을 사용할 때, 우리는 리스트 형태로 모든 값을 넣어줬습니다.

HyperOpt에서는 quniform과 uniform을 통해, 값을 지정할 수 있습니다.

  • quniform: numpy 의 arange와 동일하다고 보면 됨.
    hp.quniform('파라미터 명', start, end, step)
  • uniform: 정규 분포 형태로 만들어줌.
    hp.uniform('파라미터 명', start, end)

각 API에는 맨 먼저 파라미터 명을 써준다는 특징이 있습니다.

from hyperopt import hp

# search space 생성.
params = {'x': hp.quniform('x', 1, 15, 1), 'y': hp.uniform('y', 0.1, 1)}

Grid Search를 할 때와 마찬가지로 {파라미터: 값, ...} 형태로 작성합니다.


✔ Objective Function(목적 함수)

목적 함수라고도 불리는 Objective Function은 최종적으로 우리가 찾아야 하는 함수 입니다.
앞서 대체 모델이 만들어 내는 예측 최적함수도 목적 함수를 따라가려고 하는 겁니다.

from hyperopt import STATUS_OK

# Objective Function 생성.
def objective_function(params):
    x = params['x']
    y = params['y']

    return x ** 2 - y

목적 함수의 반환 값은 loss(손실) 값입니다.
실제 분류 프로젝트에서는 accuracy_score, f1_score, auc 등과 같은 평가 지표가 반환 값일 겁니다.

이때 주의할 점은, HyperOpt는 반환 값이 손실 값이라고 생각한다는 점입니다.
손실 값은 낮을수록 좋기 때문에 가장 낮은 손실 값을 찾으려고 노력하게 됩니다.

하지만, 분류 지표같은 경우 일반적으로 높은 값이 나와야 하기 때문에 -1을 곱해줘야 합니다.

from hyperopt import STATUS_OK
from sklearn.metrics import accuracy_score

# Objective Function 생성.
def objective_function(params):
    x = params['x']
    y = params['y']
    z = params['z']
    
          .
          .
          .
	
    clf_model = classifier(x=x, y=y, z=z, ...)
    clf_model.fit(X_train, y_train)
    
    pred = clf_model.predict(X_val)
    accuracy = accuracy_score(y_val, pred)
    
    return -1 * accuracy



✔ 파라미터 유추

HyperOpt에서는 fmin API를 통해 베이지안 최적화를 수행합니다.

fmin은 다음과 같은 파라미터가 들어갑니다.
fmin(fn, space, algo, max_evals, trials, rstate)

  • fn: Objective Function 입니다.
  • space: Search Space 입니다.
  • algo: 베이지안 최적화 적용 알고리즘 입니다. 일반적으로 tpe.suggest를 이용합니다.
    TPE(Tree of Parzen Estimator)
  • max_evals: 평가 수행 횟수 입니다.
  • trials: 반환 값 결과를 저장합니다. HyperOpt에서 제공하는 Trials 객체를 입력 받습니다.
  • rstate: random seed(랜덤 시드) 값 입니다.
from hyperopt import fmin, tpe, Trials

# 유추
trial_val = Trials()
best_param = fmin(fn=objective_function, space=params, algo=tpe.suggest, max_evals=5, trials=trial_val)

이렇게 반환된 best_param은 최적의 파라미터가 딕셔너리 형태로 저장됩니다.

또한, Trials 객체에 값들이 저장되어 있는데 주요 속성으로는 다음과 같이 있습니다.

  • Trials().results: 각 iteration마다 loss와 status가 딕셔너리 형태로 주어집니다.
  • Trials().vals: 입력 변수명과 개별 수행 시마다 입력된 값(리스트)가 딕셔너리 형태로 주어집니다.
trial_val.results

trial_val.vals




📜 Reference

[개정판] 파이썬 머신러닝 완벽 가이드
베이지안 이론(Bayesian theory)
베이즈 정리의 의미

profile
세종대학교 지능기전공학과 23

0개의 댓글