베이지안 하이퍼파라미터 최적화란 무엇일까? 튜토리얼 포함
베이지안 하이퍼파라미터 최적화에 대한 모든 궁금증을 튜토리얼과 함께 시원하게 풀어드립니다. 이 글은 AI 번역본입니다. 오역이 의심되는 부분이 있다면 댓글로 알려주세요.
Created on September 15|Last edited on September 15
Comment
Weights & Biases가 최근 출시했습니다 스위프, 모델 하이퍼파라미터를 최적화하는 정교한 방법입니다. 그 이후로 팀은 베이지안 하이퍼파라미터 최적화에 대해 많은 질문을 받아왔습니다.
- 무작위 탐색보다 더 빠른가요?
- 언제 사용해야 하나요?
- 정확히 어떻게 작동하나요?
이번 글에서는 베이지안 하이퍼파라미터 최적화에 대해 많은 분들이 가장 궁금해하는 질문들에 답해 보겠습니다. 또한 Weights & Biases를 사용해 3단계로 베이지안 탐색을 실행하는 방법도 보여드리겠습니다.
이번 글에서 다룰 내용
하이퍼파라미터란 무엇인가?그리드 서치란 무엇인가?랜덤 서치란 무엇인가?베이esian 하이퍼파라미터 최적화란 무엇인가?베이지안 하이퍼파라미터 튜닝: 핵심과 실전기대 개선대리 모델베이지안 하이퍼파라미터 최적화의 함정실전 베이지안 하이퍼파라미터 최적화보너스: 번개처럼 빠르게 Sweeps 만들기

본격적으로 들어가기 전에, 이 분야가 처음인 분들을 위해 가장 기본적인 질문부터 답해 보겠습니다.
하이퍼파라미터란 무엇인가?
머신러닝 모델의 하이퍼파라미터는 모델 성능을 최적화하기 위해 조정하는 설정값입니다. 특정 작업에 대해 올바른 하이퍼파라미터 조합을 찾는 일은 쉽지 않습니다.
더 골치 아픈 점은 머신러닝 모델이 하이퍼파라미터 구성에 매우 민감하다는 것입니다. 특정 하이퍼파라미터 구성에서 잘 동작하던 모델의 성능이 구성 값을 바꾸면 비슷하게 나오지 않을 수 있습니다.
이러한 문제를 해결하기 위해 하이퍼파라미터 튜닝을 수행합니다. 일반적인 절차는 대략 다음과 같습니다.
- 튜닝할 하이퍼파라미터를 선택합니다(머신러닝 모델에는 여러 개의 하이퍼파라미터가 있을 수 있습니다).
- 지정한 하이퍼파라미터에 대해 허용 가능한 값의 그리드를 지정하거나, 허용 가능한 값을 생성할 확률분포를 지정합니다.
- 위의 두 단계에서 정한 서로 다른 하이퍼파라미터 구성마다 해당 구성에 맞춰 여러 개의 머신러닝 모델을 학습합니다.
- 여러 모델 중에서 성능이 가장 좋은 모델을 선택합니다.
하이퍼파라미터를 효과적으로 튜닝하는 데 도움이 되는 특화된 기법들은 많지만, 가장 널리 쓰이는 방법은 다음과 같습니다:
- 그리드 서치
- 랜덤 서치
그리드 서치란 무엇인가?
그리드 서치에서는 먼저 하이퍼파라미터 목록과, 탐색 과정에서 시도할 허용 가능한 값들의 목록을 함께 담은 그리드를 정의합니다. 아래는 로지스틱 회귀 모델을 위한 하이퍼파라미터 그리드 예시입니다:

이 경우 탐색 과정에서는 총 2 × 3 × 3 × 4 = 72개의 서로 다른 로지스틱 회귀 모델을 학습하게 됩니다.
랜덤 서치란 무엇인가?
랜덤 서치에서는 하��퍼파라미터 값들의 그리드를 정의하는 대신, 지정한 하이퍼파라미터에 대해 허용 가능한 값들을 샘플링할 확률분포를 함께 지정합니다. 랜덤 서치와 그리드 서치의 핵심 차이는, 가능한 모든 하이퍼파라미터 조합을 모두 시도하는 대신 각 조합을 무작위로 샘플링한다는 점이며, 이때 하이퍼파라미터 값들은 랜덤 서치 과정을 시작할 때 미리 지정한 분포에서 추출된다는 것입니다.
방금 살펴본 일반적인 하이퍼파라미터 최적화 절차에서, 개선할 만한 점이 보였나요?
💡
우리가 지정하는 서로 다른 하이퍼파라미터 구성들은 모두 서로 독립적입니다. 이 구성들을 좀 더 지능적으로 만들 수는 없을까요? 만약 과거 결과(즉, 서로 다른 하이퍼파라미터 구성으로 실행한 결과)를 활용해 하이퍼파라미터 탐색 과정을 안내할 수 있다면 어떨까요? 그렇게 하면 튜닝 과정을 더 개선할 수 있을까요? 함께 확인해 봅시다!
시작하기에 앞서, 명확히 하기 위해 이 질문에 먼저 답해 봅시다:
베이esian 하이퍼파라미터 최적화란 무엇인가?
베이지안 하이퍼파라미터 최적화는 머신러닝 모델의 성능을 ��우하는 하이퍼파라미터, 즉 일종의 조절 “노브”들의 최적 설정을 찾기 위한 기법입니다. 앞서 언급한 전통적인 방법처럼 가능한 모든 조합을 맹목적으로 시도하는 대신, 베이지안 최적화는 이전 평가 결과에서 얻은 정보를 바탕으로 탐색을 똑똑하고 효율적으로 안내하는 접근을 사용합니다.
베이지안 하이퍼파라미터 튜닝: 핵심과 실전
베이지안 원리를 하이퍼파라미터 튜닝에 적용할 때는 일반적으로 다음과 같은 단계를 따릅니다:
- 하이퍼파라미터 값들의 조합(현재의 가설)을 선택하고 머신러닝 모델을 학습합니다.
- 증거를 수집합니다(즉, 모델의 점수를 확인합니다)
- 성능 향상으로 이어질 수 있도록 현재의 가설을 업데이트합니다.
- 중단 기준을 충족하면 탐색을 종료합니다(일반적으로 손실이 최소화되거나 분류 정확도가 최대화될 때).
조금 더 자세히 이해하기 위해 250여 년의 역사를 가진 베이즈 법칙을 소개해 보겠습니다. 이 법칙은 X가 주어졌을 때 Y를 예측하는 데 도움을 줍니다. 예를 들어, 오늘 비가 왔다면 내일 John이 축구를 할 확률은 얼마인가를 묻는 것입니다. 여기서 Y는 내일 John이 축구를 할 확률이고, X는 오늘 비가 왔다는 사실을 의미합니다. 확률론 문헌에서는 이를 다음과 같이 표기합니다 —

이는 “X가 주어졌을 때 Y의 확률은 얼마인가”로 읽습니다. 이제 우변도 있습니다:

여기서,
- P(X)는 이 새로운 증거를 관측할 확률입니다.
- P(X | Y)는 우리가 관심 있는 사건 Y가 주어졌을 때, 새로운 증거 X를 관측할 확률입니다.
- P(Y)는 우리가 관심 있는 사건 Y에 대한 초기 가설입니다(사건 Y에 대한 초기 신념으로 보면 됩니다).
따라서 같은 원리를 하이퍼파라미터 튜닝에 적용해 보면, 이에 대한 방정식은 다음과 같습니다 —

따라서 이제 위의 각 항은 다음과 같습니다:
- P(metric | 하이퍼파라미터 조합)은 특정 하이퍼파라미터 값의 조합이 주어졌을 때, 해당 지표가 최소화되거나 최대화될 확률을 의미합니다.
- P(하이퍼파라미터 조합 | 지표)는 주어진 지표가 최소화되거나 최대화될 때, 특정 하이퍼파라미터 조합일 확률입니다.
- P(metric)은 초기 스칼라 형태의 지표 값입니다.
- P(하이퍼파라미터 조합)은 해당 하이퍼파라미터 조합이 나타날 확률입니다.
이제 다양한 하이퍼파라미터 구성들을 탐색해 나가면서, 이전 실험에서 얻은 정보를 활용해 매 실행마다 더 나은 하이퍼파라미터 조합으로 모델을 학습할 수 있게 됩니다. 그런데 여전히 궁금할 수 있는 질문은 이것입니다 — 가장 크게 개선하려면 다음에 어떤 하이퍼파라미터 공간을 탐색해야 할까? 지금부터 확인해 봅시다.
베이지안 하이퍼파라미터 튜닝에서의 정보 기반 탐색 개념
다음 그림을 보세요. 특정 신경망의 학습 정확도가 에포크 수에 따라 어떻게 변하는지 보여 줍니다 —

에포크 수가 많아질수록 결과가 더 좋아지는 것을 분명히 확인할 수 있습니다. 그렇다면 이제 이 지식을 하이퍼파라미터 최적화 과정에 어떻게 활용할 수 있을까요?
베이지안 하이퍼파라미터 최적화는 우리가 최소화하거나 최대화하려는 목적 함수를 확률적 모델로 구성함으로써, 머신러닝 모델을 학습하는 과정에서 이를 활용할 수 있게 해줍니다.
그런 목적 함수의 예는 전혀 어렵지 않습니다. 정확도, 평균제곱근오차 등과 같은 지표들이 이에 해당합니다. 이 확률적 모델은 이 경우 목적 함수를 대신하는 대리 모델(surrogate model)이라고 부릅니다. 표기는 P(지표 | 하이퍼파라미터 조합), 더 일반적으로는 P(y | x)로 나타냅니다.
실험 결과, 이 대리 모델은 원래의 목적 함수보다 최적화하기 훨씬 쉽습니다. 하이퍼파라미터 최적화 과정에서 다음 하이퍼파라미터 집합은 대리 함수에서 가장 좋은 성능을 내도록 선택된다는 점을 기억하는 것이 중요합니다. 이렇게 선택된 집합은 이후 실제 목적 함수를 사용해 추가로 평가됩니다. 여기서 중요한 함정은 —
목적 함수를 호출하는 횟수가 적을수록 하이퍼파라미터 검색의 효율은 높아집니다. 데이터의 차원이 증가할수록 목적 함수를 이용해 이를 평가하는 데 드는 계산 비용이 커지기 때문입니다. 대리 모델을 사용하면 유망한 하이퍼파라미터 집합을 선택해 실제 목적 함수 호출 횟수를 줄일 수 있습니다.
이런 이유로, 하이퍼파라미터 조합이 매우 다양한 경우에는 베이지안 하이퍼파라미터 최적화가 더 바람직한 선택입니다.
이제 인간이 일반적으로 사물을 다루는 방식을 다시 떠올려 봅시다. 우리는 먼저 들어가려는 세계에 대한 초기 모델(사전분포, prior)을 세우고, 상호작용을 통해 얻은 경험(증거, evidence)에 기반해 그 모델을 갱신합니다(갱신된 모델을 사후분포, posterior라고 합니다). 이제 이 과정을 그대로 하이퍼파라미터 튜닝에 적용해 봅시다!
우리는 하이퍼파라미터에 대한 초기 추정값으로 시작하고, 과거 결과를 바탕으로 그것을 점진적으로 업데이트합니다. 다음을 그 초기 추정의 표현이라고 생각해 봅시다 —

검은 선은 대리 모델이 만든 초기 추정치를, 빨간 선은 목적 함수의 실제 값을 나타냅니다. 진행할수록 대리 모델이 목적 함수의 실제 값을 훨씬 더 촘촘하게 모사하게 됩니다:

회색 영역은 대리 모델의 불확실성을 나타내며, 이는 평균과 표준편차로 정의됩니다.
이 과정에서 다음 하이퍼파라미터 집합을 선택하려면, 해당 하이퍼파라미터 집합에 대해 확률적 점수를 산출하는 방법이 필요합니다. 점수가 높을수록 그 하이퍼파라미터 집합이 선택될 가능성이 커집니다. 일반적으로 이는 기대 개선(expected improvement)을 통해 수행합니다. 그 밖의 방법으로는 개선 확률(probability of improvement), 하한 신뢰 구간(lower confidence bound) 등이 있습니다.
기대 개선
기대 개선은 목적 함수에 임계값을 도입하고, 그 임계값을 능가하는 하이퍼파라미터 집합을 찾는 방식으로 작동합니다. 수학적으로는 다음과 같이 표현할 수 있습니다 —

여기서 —
- y*는 목적 함수의 임계값입니다
- y는 목적 함수의 실제 값입니다
- p(y | x)는 대리 모델입니다
- 위의 식은 다음 사항을 보장합니다:
특정 x(하이퍼파라미터 조합)에 대해 p(y | x)가 y* > y가 되도록 분포한다면, 그 하이퍼파라미터 조합은 임계값보다 더 나은 점수를 내지 못한다는 뜻입니다. 반대로 그렇지 않다면, 그 하이퍼파라미터 조합을 시도해 볼 가치가 있습니다.
하지만 아직 퍼즐의 마지막 조각, 즉 대리 모델을 추가해야 합니다.
대리 모델
대리 모델을 구성하는 작업은 일반적으로 회귀 문제로 모델링합니다. 하이퍼파라미터 집합과 함께 데이터를 입력으로 주면, 평균과 표준편차로 매개변수화된 목적 함수의 근사치를 반환합니다. 대리 모델로 흔히 쓰이는 선택지는 다음과 같습니다:
- 가우시안 프로세스 회귀
- 트리 구조 파르젠 추정기
첫 번째 것부터 간단히 이야기해 보겠습니다.
가우시안 프로세스는 입력 특성과 목적 함수의 실제 값에 대한 결합확률을 구성함으로써 작동합니다. 이렇게 하면 충분한 반복을 거쳤을 때 목적 함수에 대한 효과적인 추정치를 포착할 수 있습니다.
위 내용이 다소 무겁게 느껴졌다면, 베이즈적 추론의 핵심 목표는 더 많은 데이터를 통해 “덜 틀리는 것”이라는 점만 기억하셔도 됩니다.
베이지안 하이퍼파라미터 최적화의 함정
베이지안 하이퍼파라미터 최적화가 다른 튜닝 방식들과 비교했을 때 가장 합리적이지만, 다음과 같은 단점도 있습니다:
베이지안 탐색 과정은 본질적으로 순차적이어서 병렬화하기가 매우 어렵습니다. 그러나 규모 확대를 위해서는 병렬화가 필요할 수 있습니다.
적절한 대체 모델을 정의하는 일은 까다로우며, 그 자체로 하이퍼파라미터들을 갖고 있습니다.
그렇다면 이제 확인해 봅시다
실전 베이지안 하이퍼파라미터 최적화
베이지안 하이퍼파라미터 최적화를 다루는 코드를 살펴보기 전에, 먼저 필요한 구성 요소들을 정리해 봅시다.
이번 실험에는 Keras 라이브러리를 사용합니다(구체적으로는 TensorFlow 2.0 환경의 tf.keras). 데이터셋으로는 FashionMNIST를 사용하고, 얕은 합성곱 신경망 우리의 머신러닝 모델로 사용합니다. 간단한 모델은 다음과 같이 정의합니다 —
model = Sequential([Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),MaxPooling2D((2,2)),Conv2D(64, (3, 3), activation='relu'),MaxPooling2D((2,2)),Conv2D(64, (3, 3), activation='relu'),GlobalAveragePooling2D(),Dense(config.layers, activation=tf.nn.relu),Dense(10, activation='softmax')])
이 데이터셋의 이미지는 28×28 픽셀 형태로 제공됩니다. 그러나 Keras의 Conv2D 레이어와 호환되도록 28×28×1 형태로 리쉐이프해야 합니다. 계속해서, 우리의 하이퍼파라미터 검색 설정은 다음과 같습니다 —
sweep_config = {'method': method,'metric': {'name': 'accuracy','goal': 'maximize'},'parameters': {'layers': {'values': [32, 64, 96, 128, 256]},'batch_size': {'values': [32, 64, 96, 128]},'epochs': {'values': [5, 10, 15]}}}
세 가지 서로 다른 하이퍼파라미터 최적화 방법으로 동일한 실험을 수행하겠습니다: 전수 탐색(그리드), 무작위 샘플링 방식(랜덤), 그리고 더 똑똑한 추정 방식(베이지안). 우리의 목표는 모델의 핵심 하이퍼파라미터인 밀집 레이어 수, 배치 크기, 학습 사이클 수(에포크)를 미세 조정하여 목표 함수(메트릭)를 최대화하는 것입니다.
W&B의 Sweeps 기능을 사용하면 하이퍼파라미터 튜닝을 매우 쉽게 할 수 있습니다. 모델에 가장 적합한 설정을 찾아 주는 가이드형 검색 엔진과 같습니다. 데이터 준비, 모델 정의, 검색 매개변수 설정만 끝내면, 나머지는 몇 번의 클릭으로 W&B가 알아서 처리합니다.
sweep_id = wandb.sweep(sweep_config, project='project-name')wandb.agent(sweep_id, function=train)
train 함수는 지정된 하이퍼파라미터로 모델을 학습시키는 역할을 합니다.
def train():# Prepare data tuples(X_train, y_train) = train_images, train_labels(X_test, y_test) = test_images, test_labels# Default values for hyper-parameters we're going to sweep overconfigs = {'layers': 128,'batch_size': 64,'epochs': 5,'method': METHOD}# Initilize a new wandb runwandb.init(project='hyperparameter-sweeps-comparison', config=configs)# Config is a variable that holds and saves hyperparameters and inputsconfig = wandb.config# Define the modelmodel = Sequential([Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),MaxPooling2D((2,2)),Conv2D(64, (3, 3), activation='relu'),MaxPooling2D((2,2)),Conv2D(64, (3, 3), activation='relu'),GlobalAveragePooling2D(),Dense(config.layers, activation=tf.nn.relu)Dense(10, activation='softmax')])# Compile the modelmodel.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])# Train the modelmodel.fit(X_train, y_train,epochs=config.epochs,batch_size=config.batch_size,validation_data=(X_test, y_test),callbacks=[WandbCallback(data_type="image",validation_data=(X_test, y_test), labels=labels)])
각 실행마다 하이퍼파라미터 조합이 업데이트되며, 다음의 config 인자를 통해 사용할 수 있습니다 wandbW&B를 사용한 하이퍼파라미터 스윕의 세부 사항까지 깊이 들어가는 내용은 이 글의 범위를 벗어나지만, 관심이 있다면 다음 글들을 참고하시길 권합니다 —
앞서 언급했듯이, 우리는 그리드 서치, 랜덤 서치, 베이지안 서치 세 가지 방법으로 스윕을 실행할 것입니다. 이제 이 세 가지의 대결을 시작해 봅시다!
W&B의 장점은 새 스윕을 시작할 때마다 별도의 Sweeps 페이지를 자동으로 만들어 준다는 점입니다. 그리드 서치 실험에 포함된 실행(run)들은 확인할 수 있습니다 여기 시각화해 봅시다. 주목해야 할 핵심 플롯은 다음과 같습니다:

그다음으로 넘어가기 전에, 랜덤 서치와 베이지안 서치에서 얻은 플롯을 먼저 보여 드리겠습니다 —


위의 세 가지 플롯에서 가장 주목해야 할 점은 최대값에 도달하기까지 해당 방법이 수행한 서로 다른 실행(run)의 수입니다. val_accuracy여기서는 하이퍼파라미터 조합이 달라질 때마다 서로 다른 실행(run)으로 간주합니다. 보시다시피, 베이지안 서치는 원하는 결과에 도달하는 데 필요한 실행 수가 가장 적습니다.
여기서 중요한 점은 랜덤 서치와 베이지안 서치 모두에서, 원하는 결과에 도달하면 검색 프로세스를 수동으로 종료해야 한다는 것입니다. 실행 중일 때 해당 Sweeps 페이지로 이동한 다음 Sweep Controls로 들어가면 쉽게 종료할 수 있습니다.

그 버튼을 클릭하면 다음과 같은 페이지로 이동하며, 거기서 스윕을 완전히 제어할 수 있습니다 —



또 하나의 장점은, 손실(loss), 검증 손실(val_loss), 정확도(accuracy), 검증 정확도(val_accuracy)와 같은 핵심 지표들을 함께 비교해 보면 베이지안 하이퍼파라미터 최적화가 베이지안 검색 과정의 우수성을 분명하게 보여 준다는 점입니다.

보너스: 번개처럼 빠르게 Sweeps 만들기

이미 실행 기록이 있는 기존 W&B Sweeps 프로젝트를 가져와, 구성 변수에 기반한 새로운 스윕을 빠르게 생성할 수 있게 해줍니다.
이제, 제가 할 일은 —
- 기본 구성 파일(sweep.yaml)을 다운로드하세요(직접 구성할 수도 있습니다).
- 학습 함수를 Python 스크립트로 묶어 train.py라는 이름을 지정하세요. 스크립트는 다음에서 확인할 수 있습니다 여기.
- 위 스냅샷의 지시에 따르세요.
자, 끝입니다! 이제 스윕이 실행되기 시작할 것입니다 —

그렇다면, 당신은 얼마나 베이지안한가요?
이 글은 여기까지입니다. 하이퍼파라미터 최적화에 관심이 있다면 James Bergstra의 연구를 꼭 확인해 보세요 —
머신러닝 모델의 하이퍼파라미터를 조정하기 위한 베이지안 탐색 과정에 대해 충분히 소개받으셨길 바랍니다. 베이지안 탐색이 여러분의 프로젝트에 얼마나 큰 도움이 되는지 정말 기대됩니다. 결과와 경험을 아래 댓글로 공유해 주세요!
Add a comment