베이지안 최적화(Bayesian Optimization)란?
베이지안 최적화는 머신러닝에서 하이퍼파라미터 튜닝을 똑똑하게, 그리고 효율적으로 수행하기 위한 방법. 하이퍼파라미터는 모델을 학습시키기 전에 사람이 직접 설정해야 하는 값들인데, 이 값들이 모델의 성능에 큰 영향을 미침. 예를 들어 학습률(learning rate)이나 트리의 깊이 같은 것들이 하이퍼파라미터.
문제는 이 값들을 무작정 시도해보는 건 시간도 오래 걸리고 비효율적이라는 점
다른 하이퍼 파라미터 튜닝 방법
그리드 서치(Grid Search)
- 가능한 하이퍼파라미터 값들을 미리 정하고, 모든 조합을 하나씩 시도함
- 장점: 최적의 조합을 놓칠 가능성이 적음
- 단점: 조합이 많아지면 시간이 너무 오래 걸림
랜덤 서치(Random Search)
- 하이퍼파라미터 값 범위에서 무작위로 조합을 골라 테스트함
- 장점: 더 넓은 범위를 빠르게 탐색할 수 있음
- 단점: 운이 나쁘면 좋은 조합을 놓칠 수도 있음
이런 문제들 때문에 베이지안 최적화가 등장함
베이지안 최적화는 이전 테스트 결과를 보고 다음에 시도할 조합을 똑똑하게 예측함
베이지안 최적화의 기본 아이디어 쉽게 이해하기
베이지안 최적화는 두 가지 중요한 도구를 사용함
대체 모델(Surrogate Model)
- 우리가 최적화하려는 진짜 함수(목적 함수)를 대신해서 근사해주는 모델
- 진짜 함수를 매번 계산하는 건 비용이 많이 들 수 있으니, 대체 모델이 “이 함수는 대충 이렇게 생겼을 거야"라고 예측함
- 주로 **가우시안 프로세스(Gaussian Process)**라는 통계 모델을 사용함. 이건 함수의 값뿐만 아니라 그 값이 얼마나 확실한지(불확실정)도 같이 알려줌
획득 함수(Acquisition Function)
- 대체 모델이 예측한 정보를 바탕으로 “다음엔 어디를 시도해볼까?“를 결정하는 함수
- 이 함수는 두 가지를 고려함
- 탐색(Exploration): 아직 잘 모르는 영역을 시도해보자
- 활용(Exploitation): 지금까지 좋은 성능을 보인 곳 근처를 더 파보자
- 이 균형을 잘 맞춰서 다음 시도 지점을 똑똑하게 골라줌
베이지안 최적화의 동작을 단계별로 알아보기
베이지안 최적화가 실제로 어떻게 작동하는지, 예시를 통해 단계별로 알아보겠음 우리가 어떤 함수의 최소값을 찾고 있다고 생각해보면 ex: $f(x) = (x-2)^2$
- 초기화
- 처음엔 어디가 좋은지 모르니까, 몇 개의 하이퍼파라미터 조합을 무작위로 골라서 성능을 평가함
- ex: $x = 0$일 때 $f(0) = 4, x = 5$일때 $f(5) = 9$ 이런 식으로 몇 번 시도해봄
- 대체 모델 학습
- 이 데이터를 바탕으로 대체 모델(가우시안 프로세스)이 “이 함수는 대략 이렇게 생겼을 거야"라고 예측함
- 동시에 “여긴 확실하고, 여긴 좀 불확실해"라는 정보도 같이 줌
- 획득 함수로 다음 지점 선택
- 획득 함수가 대체 모델을 보고 “여기 시도하면 좋을 것 같아"라고 추천해줌
- ex: “$x = 2$ 근처가 좋아 보이네” 라고 예측할 수 있음
- 모델 평가
- 추천받은 $x = 2$를 실제로 넣어서 함수 값을 계산해봄. $f(2) = 0$이 나옴. “오 이거 좋은데” 싶음
- 이 결과를 다시 데이터에 추가함
- 반복
- 새로운 데이터를 대체 모델에 반영하고, 다시 획득 함수로 다음 지점을 찾는 과정을 반복함
- 점점 더 좋은 값에 가까워짐
베이지안 최적화의 장점과 단점
장점
- 효율성: 무작위로 시도하는 것보다 훨씬 적은 시도로 좋은 하이퍼파라미터를 찾을 수 있음
- 똑똑한 선택: 이전 결과를 바탕으로 어디를 시도할지 예측하니까 시간과 비용이 절약됨
- 비용이 높은 경우에 특히 유용: 모델 학습에 하루씩 걸리는 상황이라면, 베이지안 최적화가 큰 도움이 됨
단점
- 조금 복잡함: 가우시안 프로세스나 획득 함수를 이해하려면 약간의 수학적 배경이 필요함
- 계산 비용: 대체 모델 자체를 학습시키는 데 시간이 걸릴 수 있음
- 한계: 하이퍼파라미터가 너무 많아지면(고차원) 효율이 떨어질 수 있음
예시 코드
|
|
을 실행하면
|
|
이렇게 최적화 결과로 res.x[0]
이 약 2
에 가깝게 나오고, rest.fun
은 0
에 가까운 값이 나옴