본문 바로가기

Data Science/Machine Learning

[ML] Bayesian Optimization으로 파라미터 튜닝하기

반응형

이번 포스팅에서는 머신러닝 모델의 하이퍼파라미터를 튜닝하는 방법 중 하나인 Bayesian Optimization에 대해 알아보려 한다. 그리고 간단한 예시를 통해 Bayesian Optimization 라이브러리가 얼마나 최적의 해와 근사하게 구하는지도 살펴보자. 참고로 Bayesian Optimization의 디테일한 수학적 수식보단 직관적인 이해와 어떤 과정으로 Bayesian Optimization이 수행되는지에 초점을 맞추었다. 자세한 수학적 수식은 하단의 레퍼런스를 참조하자.

 

Bayesian Optimization은 Bayesian Rule과 관련되어 있다.

 

하이퍼파라미터 튜닝은 머신러닝 모델의 성능을 향상시키는 데 상당한 기여를 한다. 경우에 따라 모델이 너무 복잡해 발생하는 Overfitting 문제도 예방할 수 있으며 반대로 모델이 너무 단순하여 발생하는 Underfitting 문제를 막기도 한다. 그렇다면 최고의 하이퍼파라미터 조합을 찾기 위해서는 어떻게 해야할까? 

 

크게 3가지 방법이 존재하는데, 모든 조합을 다 대입해보면서 찾아내는 Grid Search 방법, 다양한 경우의 수 중 랜덤하게 선택하여 최적의 파라미터는 찾는 Random Search 방법, 그리고 이번에 소개할 Bayesian Optimization 방법이 있다.

 

Grid Search 방법은 모든 경우의 수를 탐색하는 방법이기 때문에 주로 데이터셋이 작은 경우에 효과를 볼 수 있다. 반면 큰 데이터셋에 Grid Search를 적용한다면 최적의 파라미터를 찾아내는 데 상당한 많은 시간이 소요된다. 그래서 큰 데이터셋에서는 Grid Search 보다 Random Search가 더 권장된다고 한다. Grid Search와 Random Search에 대한 자세한 프로세스는 여기의 How to model in many hyperparameters 목차를 참고하자.

Bayesian Optimization

Bayesian Optimization란, 미지의 함수(Black-box function이라고 부른다)가 반환하는 값의 최대(또는 최소)값을 짧은 반복을 통해서 찾아내는 최적화 방식이다. 즉, 하나의 데이터 관측치를 관찰하면서 Bayesian Rule의 목적인 Posterior Probability(사후 확률) 분포를 계속적으로 업데이트한다. 이 때 사후확률을 생성하기 위해 Gaussian Process를 이용한다. 그리고 데이터 관측치를 반복적으로 관찰하면서 사후 확률 분포가 점점 개선되고 결국 미지의 함수가 반환하는 최대(또는 최소)값을 반환한다. 그래서 큰 데이터셋에서 Grid Search나 Random Search 방법들보다 상대적으로 최적의 파라미터를 찾는 데 걸리는 시간이 대폭 줄어든다.  Bayesian Optimization의 보다 자세한 프로세스를 살펴보기 위해 다음 그림을 보자.

 

 

위 그래프에서 빨간색 점선은 찾으려고 하는 미지의 함수를 의미하며 검은색 실선은 검은색 동그라미(관측 데이터)들을 바탕으로 예측한 추정 함수의 expectation을 의미한다. 그리고 회색의 영역은 미지의 함수 f(x)가 존재할 신뢰 구간이라고 보면 된다. 

 

그리고 그래프 하단의 EI(x)는 Acquisition function을 의미한다. 여기서 Acquisition function을 알기 위해서 다음과 같은 이론을 이해해보자.

 

우선 Bayesian Optimization에는 Surrogate model과 Acquisition function 으로 나뉘게 된다. Surrogate model지금까지 추론한 결과들을 바탕으로 미지의 함수 f(x)의 대략적인 값을 추정하는 것이다. 이 대략적인 값을 추정하는 방법은 Gaussian Process를 많이 사용한다. 위 예시 그래프를 보면, 검은색 동그라미는 이미 관측한 데이터이며 검은색 동그라미에서 멀어질 수록 회색 구간이 넓어지는 것을 볼 수 있다. 이는 검은색 동그라미 지점에서는 (이미 관측한 데이터이므로)불확실성이 0에 가까우며(그래서 회색영역이 매우 좁다) 반대로 검은색 동그라미 지점에서 멀어지면서 회색 영역이 넓어지며 결국 불확실성이 커짐을 의미한다.

 

다음은 Acquisition function이다. Acquisition function이란, Surrogate model의 확률분포를 이용해서 나온 확률분포를 이용해 지금까지 나온 값들보다 더 큰 값이 나올 가능성이 제일 높은 점을 알려주는 함수이다. 위 그래프 하단의 EI(x)를 보면 파란색 동그라미를 살펴보자. 파란색 동그라미가 EI(x) 확률분포 중 가장 큰 값을 나올 곳을 의미한다. 

 

이제 Acquisition function값이 제일 컸던 지점의 함수값을 관측하고 다음 추정을 업데이트 한 다음 그림을 보자. 업데이트 이전의 EI(x)값이 가장 높을 것으로 추정된 위치의 데이터를 관측한 후 해당 부분의 회색영역이 크게 줄어들었음을 볼 수 있다.

 

 

하지만 아직 역시 EI(x) 확률분포를 살펴보면 좌측 부분의 불확실성의 값이 여전히 큼을 알 수 있다. 따라서 이 불확실성 영역을 축소시키기 위해서 파란색 동그라미 지점의 관측 데이터를 미지의 함수에 입력했을 때 반환되는 값을 관측하고 추정을 또 업데이트 한다. 다음 그림을 보면 검은색 실선(예측값)빨간색 점선(찾으려는 미지의 함수인 타겟값)과 거의 비슷해짐을 볼 수 있다.

 

 

그렇다면 EI(x)의 가장 큰 값인 파란색 동그라미를 찾기 위해서는 어떻게 할까? 다음과 같은 2가지 방법이 있다. 바로 Exploration과 Exploitation 방법이다. 의미는 다음과 같다.

 

  • Exploration : 불확실성이 가장 높은 곳에서 지금까지 나온 관측값들보다 큰(또는 작은) 값이 나올 것이라는 사고
  • Exploitation(Expectation) : 지금까지 관측된 값들 중에서 높은 값들 근처에 더 큰(또는 작은)값이 나올 것이라는 사고

이 2가지 방법을 적절하게 균형을 이루어 Acquisition function을 만들어낸다. Exploration과 Exploitation 방법은 강화학습에서도 언급되는 용어임을 참고로 알아두자.(기회가 되면 추후에 지난 학기에 배운 강화학습의 기본 내용에 대해 포스팅 하려고 한다)

Bayesian Optimization이 찾은 최적의 해와 전역 해를 비교해보기

Bayesian Optimization의 Github 링크에서 예시로 제공해주는 코드를 활용해서 Bayesian Optimization이 찾은 최적의 해와 전역 해가 얼마나 차이가 나는지 간단한 코드로 확인해보자.

 

# 미지의 함수 f(x)를 사전에 정의
def black_box_func(x, y):
    return -x ** 2 - (y-1) ** 2 + 1
    
# Search할 하이퍼파라미터 범위 정의
pbounds = {'x': (2, 40), 'y': (-3, 30)}

# Bayesian Optimization을 이용해서 최적의 파라미터 찾아내기
from bayes_opt import BayesianOptimization

optimizer = BayesianOptimization(f=black_box_func,
                                pbounds=pbounds,
                                random_state=40)
# 미지의 함수 반환값을 최대화하도록 반복하면서 최적의 파라미터 검색
optimizer.maximize(init_points=2,
                  n_iter=10)

 

Bayesian Optimization 결과값이 다음과 같이 나왔다. x, y는 하이퍼파라미터 종류, target은 x, y 파라미터를 미지의 함수에 대입했을 때 나오는 값을 의미한다. 

 

결과값

 

빨간색 네모칸을 보면 target값이 최대가 되도록 하는 파라미터는 x값이 2.0이고 y값이 1.068일 때이다. 이제 일일이 x, y의 파라미터 값 범위를 지정해서 loop를 이용해 결과값이 최대값이 되는 전역의 해를 찾아보자.

 

# 미지의 함수의 전역 해 찾아내기
import numpy as np

res = -9999
x_val = -9999
y_val = -9999
iter_cnt = 0
# 하이퍼파라미터 x, y 값들 모두 넣기
for x in np.arange(2, 40.1, 0.1):
    for y in np.arange(-3, 30.1, 0.1):
        # 미지의 함수에 파라미터 입력 후 결과값 반환
        curr_res = black_box_func(x, y)
        iter_cnt += 1
        # curr_res값을 res에 재할당함으로써 최댓값으로 업데이트
        if curr_res > res:
            res = curr_res
            x_val = x
            y_val = y
print("Iteration 횟수:", iter_cnt)
print("Result:", res)
print("X값:", x_val)
print("Y값:", y_val)

 

결과값은 다음과 같다. x값은 2, y값은 대략 1이 나왔다. Bayesian Optimization으로 도출해낸 최적의 파라미터 조합(x = 2.0, y = 1.068) 일 때와 거의 근사함을 알 수 있다.

 

결과값

 

# Reference

sanghyukchun.github.io/99/

 

Practical Bayesian Optimization of Machine Learning Algorithms (NIPS 2012) - README

들어가며 Machine Learning 모델을 만들다보면 Hyperparameter 라는 녀석을 다뤄야 하는 일이 종종 발생한다. 예를 들면 Random forest의 forest 개수라거나, Neural network의 layer 개수, learning rate, momentum 값 등등..

sanghyukchun.github.io

brunch.co.kr/@tristanmhhd/19

 

Bayesian Optimization

Hyperparameter tuning | Optimization Optimization은 어떤 임의의 함수 f(x)의 값을 가장 크게(또는 작게)하는 해를 구하는 것이다. 이 f(x)는 머신러닝에서 어떤 임의의 모델이다. 예를 들어 f(x)를 딥러닝 모델

brunch.co.kr

github.com/fmfn/BayesianOptimization

 

fmfn/BayesianOptimization

A Python implementation of global optimization with gaussian processes. - fmfn/BayesianOptimization

github.com

 

반응형