콘텐츠로 이동
Data Prep
상세

Bayesian Optimization (베이지안 최적화)

메타 정보

항목 내용
분류 Optimization / AutoML / Hyperparameter Tuning / Black-Box Optimization
핵심 논문 "Practical Bayesian Optimization of Machine Learning Algorithms" (Snoek, Larochelle & Adams, NeurIPS 2012), "Algorithms for Hyper-Parameter Optimization" (Bergstra et al., NeurIPS 2011), "Taking the Human Out of the Loop: A Review of Bayesian Optimization" (Shahriari et al., IEEE 2016), "A Tutorial on Bayesian Optimization" (Frazier, arXiv 2018), "Understanding High-Dimensional Bayesian Optimization" (Hvarfner et al., arXiv 2025), "BOHB: Robust and Efficient Hyperparameter Optimization at Scale" (Falkner et al., ICML 2018)
주요 저자 Jasper Snoek (GP-based BO), James Bergstra (TPE, Hyperopt), Frank Hutter (SMAC, BOHB), Peter Frazier (Tutorial/Theory), Eytan Bakshy (BoTorch/Ax)
핵심 개념 평가 비용이 높은 블랙박스 함수의 전역 최적화를 위해, 대리 모델(Surrogate Model)과 획득 함수(Acquisition Function)를 반복적으로 사용하는 순차적 모델 기반 최적화(SMBO)
관련 분야 AutoML, Hyperparameter Tuning, Neural Architecture Search, Experimental Design, Active Learning

정의

Bayesian Optimization(BO)은 평가 비용이 크고 그래디언트 정보가 없는 블랙박스 함수 f(x)의 전역 최적점을 최소한의 평가 횟수로 찾기 위한 순차적 최적화 프레임워크이다. BO는 두 가지 핵심 구성요소로 동작한다:

  1. Surrogate Model: 관측 데이터를 기반으로 목적 함수의 사후 분포(posterior)를 추정하는 확률적 모델
  2. Acquisition Function: 다음 평가 지점을 결정하는 기준으로, exploration(탐험)과 exploitation(활용) 사이의 균형을 조절
Bayesian Optimization 루프:

[초기화] n개 랜덤 포인트 평가
  |
  v
[반복 시작] ----+
  |              |
  v              |
Surrogate Model 업데이트          |
(GP, TPE, RF 등으로 f(x) 근사)   |
  |              |
  v              |
Acquisition Function 최적화       |
(EI, UCB, PI 등으로 x_next 선택)  |
  |              |
  v              |
x_next에서 f(x_next) 평가         |
  |              |
  v              |
데이터셋에 (x_next, y_next) 추가  |
  |              |
  +-- 예산 남음? -+
  |
  v
최적점 x* 반환

머신러닝에서 BO는 주로 하이퍼파라미터 최적화(HPO)에 사용되며, Grid Search나 Random Search 대비 동일 예산에서 2-10배 더 효율적으로 최적 하이퍼파라미터를 찾는다 (Snoek et al., 2012).

핵심 원리

1. Surrogate Model (대리 모델)

목적 함수를 근사하는 확률적 모델로, 각 후보 점에서의 예측값(mean)과 불확실성(variance)을 동시에 제공한다.

Gaussian Process (GP)

가장 전통적인 surrogate model. 관측 데이터에 대한 폐쇄형(closed-form) 사후 분포를 제공한다.

import numpy as np
from scipy.stats import norm
from scipy.optimize import minimize

class GaussianProcessBO:
    """
    Gaussian Process 기반 Bayesian Optimization

    GP 사후 분포:
      mu(x) = k(x, X) [K + sigma^2 I]^{-1} y
      sigma^2(x) = k(x, x) - k(x, X) [K + sigma^2 I]^{-1} k(X, x)

    여기서:
      k: 커널(공분산) 함수
      K: 학습 데이터 간 커널 행렬
      sigma^2: 관측 노이즈
    """

    def __init__(self, kernel='rbf', length_scale=1.0, noise=1e-6):
        self.length_scale = length_scale
        self.noise = noise
        self.X_train = None
        self.y_train = None

    def rbf_kernel(self, X1, X2):
        """RBF (Squared Exponential) 커널"""
        sqdist = np.sum(X1**2, axis=1).reshape(-1, 1) + \
                 np.sum(X2**2, axis=1) - \
                 2 * X1 @ X2.T
        return np.exp(-0.5 * sqdist / self.length_scale**2)

    def fit(self, X, y):
        self.X_train = X
        self.y_train = y
        K = self.rbf_kernel(X, X) + self.noise * np.eye(len(X))
        self.K_inv = np.linalg.inv(K)

    def predict(self, X_test):
        """사후 분포의 평균과 분산 반환"""
        K_s = self.rbf_kernel(X_test, self.X_train)
        K_ss = self.rbf_kernel(X_test, X_test)

        mu = K_s @ self.K_inv @ self.y_train
        sigma2 = np.diag(K_ss - K_s @ self.K_inv @ K_s.T)

        return mu, np.maximum(sigma2, 1e-10)

    def expected_improvement(self, X, xi=0.01):
        """
        Expected Improvement (EI) 획득 함수

        EI(x) = (mu(x) - f_best - xi) * Phi(Z) + sigma(x) * phi(Z)
        Z = (mu(x) - f_best - xi) / sigma(x)

        xi: exploitation/exploration 트레이드오프 파라미터
        """
        mu, sigma2 = self.predict(X)
        sigma = np.sqrt(sigma2)

        f_best = np.max(self.y_train)

        with np.errstate(divide='warn'):
            Z = (mu - f_best - xi) / sigma
            ei = (mu - f_best - xi) * norm.cdf(Z) + sigma * norm.pdf(Z)
            ei[sigma < 1e-10] = 0.0

        return ei

    def upper_confidence_bound(self, X, kappa=2.0):
        """
        Upper Confidence Bound (UCB) 획득 함수

        UCB(x) = mu(x) + kappa * sigma(x)
        kappa: exploration 강도 (높을수록 탐험적)
        """
        mu, sigma2 = self.predict(X)
        return mu + kappa * np.sqrt(sigma2)

    def optimize(self, objective_fn, bounds, n_init=5, n_iter=25,
                 acq='ei'):
        """
        Bayesian Optimization 메인 루프

        Args:
            objective_fn: 평가할 블랙박스 함수
            bounds: 각 차원의 탐색 범위 [(low, high), ...]
            n_init: 초기 랜덤 평가 수
            n_iter: BO 반복 수
            acq: 획득 함수 ('ei' 또는 'ucb')
        """
        dim = len(bounds)

        # 초기 랜덤 샘플링
        X_init = np.random.uniform(
            [b[0] for b in bounds],
            [b[1] for b in bounds],
            size=(n_init, dim)
        )
        y_init = np.array([objective_fn(x) for x in X_init])

        self.fit(X_init, y_init)

        for i in range(n_iter):
            # 획득 함수 최적화 (multi-start L-BFGS-B)
            best_x = None
            best_acq = -np.inf

            for _ in range(10):  # 10개 랜덤 시작점
                x0 = np.random.uniform(
                    [b[0] for b in bounds],
                    [b[1] for b in bounds]
                )

                if acq == 'ei':
                    acq_fn = lambda x: -self.expected_improvement(
                        x.reshape(1, -1)
                    )[0]
                else:
                    acq_fn = lambda x: -self.upper_confidence_bound(
                        x.reshape(1, -1)
                    )[0]

                result = minimize(
                    acq_fn, x0, bounds=bounds, method='L-BFGS-B'
                )

                if -result.fun > best_acq:
                    best_acq = -result.fun
                    best_x = result.x

            # 새 점 평가 및 데이터 추가
            y_new = objective_fn(best_x)
            self.X_train = np.vstack([self.X_train, best_x])
            self.y_train = np.append(self.y_train, y_new)
            self.fit(self.X_train, self.y_train)

            print(f"Iter {i+1}: x={best_x}, y={y_new:.4f}, "
                  f"best={np.max(self.y_train):.4f}")

        best_idx = np.argmax(self.y_train)
        return self.X_train[best_idx], self.y_train[best_idx]

Tree-structured Parzen Estimator (TPE)

GP의 O(n^3) 스케일링 문제를 피하는 대안적 surrogate. p(x|y)를 직접 모델링하는 대신, p(y < y*) 여부에 따라 두 개의 분포 l(x), g(x)를 구축한다 (Bergstra et al., NeurIPS 2011).

import optuna

def tpe_optimization_example():
    """
    TPE 기반 하이퍼파라미터 최적화 (Optuna)

    TPE 핵심 아이디어:
      p(x|y) 대신 p(y|x)를 모델링하는 것이 아니라,
      관측을 y* 기준으로 분할:
        l(x) = p(x | y < y*)  (좋은 관측에서의 x 분포)
        g(x) = p(x | y >= y*)  (나쁜 관측에서의 x 분포)

      EI에 비례하는 기준: l(x) / g(x) 를 최대화
      -> l(x)이 높고 g(x)가 낮은 곳 = 좋은 결과 가능성 높은 곳
    """
    from sklearn.datasets import make_classification
    from sklearn.model_selection import cross_val_score
    from sklearn.ensemble import GradientBoostingClassifier

    X, y = make_classification(n_samples=1000, n_features=20,
                               random_state=42)

    def objective(trial):
        params = {
            'n_estimators': trial.suggest_int('n_estimators', 50, 500),
            'max_depth': trial.suggest_int('max_depth', 2, 10),
            'learning_rate': trial.suggest_float(
                'learning_rate', 1e-3, 0.3, log=True
            ),
            'subsample': trial.suggest_float('subsample', 0.5, 1.0),
            'min_samples_split': trial.suggest_int(
                'min_samples_split', 2, 20
            ),
            'min_samples_leaf': trial.suggest_int(
                'min_samples_leaf', 1, 10
            ),
        }

        clf = GradientBoostingClassifier(**params, random_state=42)
        scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
        return scores.mean()

    # TPE sampler (Optuna 기본값)
    study = optuna.create_study(
        direction='maximize',
        sampler=optuna.samplers.TPESampler(
            n_startup_trials=10,   # 초기 랜덤 평가 수
            n_ei_candidates=24,    # EI 후보 수
            gamma=lambda n: min(int(np.ceil(0.25 * n)), 25),  # 상위 25%
            seed=42
        )
    )
    study.optimize(objective, n_trials=100, show_progress_bar=True)

    print(f"Best accuracy: {study.best_value:.4f}")
    print(f"Best params: {study.best_params}")
    return study

2. Acquisition Functions (획득 함수)

surrogate model의 예측을 기반으로 다음 평가 지점을 결정하는 핵심 전략.

획득 함수 수식 특징
Expected Improvement (EI) E[max(f(x) - f_best, 0)] 가장 널리 사용, exploitation 편향 가능
Upper Confidence Bound (UCB) mu(x) + kappa * sigma(x) kappa로 exploration 조절, 이론적 보장
Probability of Improvement (PI) P(f(x) > f_best + xi) 간단하지만 지나친 exploitation
Knowledge Gradient (KG) 한 번 더 평가 시 최적값 개선 기대치 이론적으로 우수, 계산 비용 높음
Thompson Sampling surrogate에서 샘플 추출 후 최적화 자연스러운 exploration, 병렬화 용이
Entropy Search (ES) 최적점 위치에 대한 정보 이득 이론적으로 우수, 매우 비쌈

3. Surrogate Model 비교

모델 시간 복잡도 장점 단점 대표 프레임워크
Gaussian Process O(n^3) 불확실성 정량화, 이론적 기초 고차원/대규모 스케일링 BoTorch, GPyOpt
TPE O(n log n) 조건부 파라미터 처리, 빠름 파라미터 간 상호작용 미약 Optuna, Hyperopt
Random Forest (SMAC) O(n log n) 범주형 처리, 고차원 가능 불확실성 추정 근사적 SMAC3
Deep Ensemble O(n) (학습 후) 고차원, 신경망 친화 학습 비용, 불확실성 보정 DeepHyper
Bayesian Neural Network O(n) (학습 후) 유연한 함수 근사 수렴 불안정 DNGO

4. 고차원 Bayesian Optimization

표준 BO는 차원이 20을 초과하면 성능이 급격히 저하된다 (Hvarfner et al., 2025). 이를 해결하기 위한 접근법:

from botorch.models import SingleTaskGP
from botorch.acquisition import ExpectedImprovement
from botorch.optim import optimize_acq_function
from gpytorch.mlls import ExactMarginalLogLikelihood
import torch

def high_dimensional_bo_example():
    """
    BoTorch를 활용한 고차원 BO 예시

    고차원 대응 전략:
    1. Random Embedding (REMBO): 고차원 -> 저차원 랜덤 임베딩
    2. Additive Models: f(x) = sum_i f_i(x_Si), 저차원 부분함수 합
    3. Trust Region (TuRBO): 지역 탐색 영역을 동적 관리
    4. SAASBO: Sparse Axis-Aligned Subspace, 축 정렬 희소 GP
    """
    # 데이터 생성 (20차원 예시)
    dim = 20
    train_X = torch.rand(30, dim, dtype=torch.double)
    train_Y = torch.sin(train_X.sum(dim=-1, keepdim=True))

    # GP 모델 정의 및 학습
    gp = SingleTaskGP(train_X, train_Y)
    mll = ExactMarginalLogLikelihood(gp.likelihood, gp)

    from botorch.fit import fit_gpytorch_mll
    fit_gpytorch_mll(mll)

    # Expected Improvement 획득 함수
    best_f = train_Y.max()
    ei = ExpectedImprovement(model=gp, best_f=best_f)

    # 획득 함수 최적화
    bounds = torch.stack([
        torch.zeros(dim, dtype=torch.double),
        torch.ones(dim, dtype=torch.double)
    ])

    candidate, acq_value = optimize_acq_function(
        acq_function=ei,
        bounds=bounds,
        q=1,            # 1개 후보
        num_restarts=10,
        raw_samples=512,
    )

    return candidate


def turbo_concept():
    """
    TuRBO (Trust Region Bayesian Optimization) 개념

    Eriksson et al., NeurIPS 2019

    핵심 아이디어:
    - 전체 탐색 공간 대신 신뢰 영역(trust region) 내에서만 BO 수행
    - 성공 시 영역 확장, 실패 시 영역 축소
    - 여러 독립적 trust region을 병렬 관리 (TuRBO-m)

    Trust Region 크기 업데이트:
      성공 (f_new > f_best): tau_succ += 1
        if tau_succ >= tau_succ_tol: L *= 2 (영역 확장)
      실패: tau_fail += 1
        if tau_fail >= tau_fail_tol: L /= 2 (영역 축소)
      L < L_min 이면 trust region 재시작
    """
    pass  # 개념 설명용

5. 멀티 피델리티 및 조기 종료

비용이 다른 여러 평가 소스(fidelity)를 활용하여 효율성을 극대화한다.

def multi_fidelity_bo_example():
    """
    Multi-Fidelity Bayesian Optimization

    BOHB (Falkner et al., ICML 2018):
      - TPE (Bayesian Optimization) + HyperBand (조기 종료)
      - 저 예산(low fidelity)에서 많은 설정 탐색
      - 유망한 설정만 고 예산(high fidelity)으로 승격

    Successive Halving 스케줄 예시 (max_budget=81, eta=3):
      Round 0: 81개 설정, 각 1 epoch   -> 상위 27개 선택
      Round 1: 27개 설정, 각 3 epoch   -> 상위 9개 선택
      Round 2:  9개 설정, 각 9 epoch   -> 상위 3개 선택
      Round 3:  3개 설정, 각 27 epoch  -> 상위 1개 선택
      Round 4:  1개 설정, 81 epoch     -> 최종 결과
    """
    from sklearn.datasets import make_classification
    from sklearn.model_selection import cross_val_score
    from sklearn.neural_network import MLPClassifier

    X, y = make_classification(n_samples=2000, n_features=30,
                               random_state=42)

    def objective_with_fidelity(params, budget):
        """
        budget: epoch 수 (fidelity)
        저예산 평가는 빠르지만 노이즈가 크고,
        고예산 평가는 정확하지만 비용이 큼
        """
        clf = MLPClassifier(
            hidden_layer_sizes=(params['hidden_size'],) * params['n_layers'],
            learning_rate_init=params['lr'],
            max_iter=int(budget),
            random_state=42
        )
        scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
        return scores.mean()

    # Optuna 기반 Multi-Fidelity
    import optuna

    def objective(trial):
        params = {
            'hidden_size': trial.suggest_int('hidden_size', 16, 256),
            'n_layers': trial.suggest_int('n_layers', 1, 4),
            'lr': trial.suggest_float('lr', 1e-4, 1e-1, log=True),
        }

        # Pruning (조기 종료) 활용
        for budget in [10, 30, 100]:
            score = objective_with_fidelity(params, budget)
            trial.report(score, step=budget)

            if trial.should_prune():
                raise optuna.TrialPruned()

        return score

    study = optuna.create_study(
        direction='maximize',
        pruner=optuna.pruners.HyperbandPruner(
            min_resource=10,
            max_resource=100,
            reduction_factor=3
        )
    )
    study.optimize(objective, n_trials=50)
    return study

6. 제약 조건 및 다목적 최적화

def constrained_bo_example():
    """
    제약 조건이 있는 Bayesian Optimization

    실제 응용에서는 단순 성능 최적화가 아니라
    추론 시간, 모델 크기, 메모리 사용량 등의 제약이 존재
    """
    import optuna

    def objective(trial):
        n_layers = trial.suggest_int('n_layers', 1, 6)
        n_units = trial.suggest_int('n_units', 16, 512)
        lr = trial.suggest_float('lr', 1e-5, 1e-1, log=True)

        # 정확도 (최대화 대상)
        accuracy = simulate_training(n_layers, n_units, lr)

        # 제약 조건: 모델 파라미터 수 < 100만
        n_params = n_layers * n_units * n_units
        trial.set_user_attr('n_params', n_params)

        if n_params > 1_000_000:
            raise optuna.TrialPruned()

        return accuracy

    # 다목적 최적화 (정확도 vs 추론 속도)
    def multi_objective(trial):
        n_layers = trial.suggest_int('n_layers', 1, 6)
        n_units = trial.suggest_int('n_units', 16, 512)

        accuracy = simulate_accuracy(n_layers, n_units)
        latency = simulate_latency(n_layers, n_units)

        return accuracy, latency  # maximize, minimize

    study = optuna.create_study(
        directions=['maximize', 'minimize'],
        sampler=optuna.samplers.TPESampler(seed=42)
    )
    # study.optimize(multi_objective, n_trials=100)
    # 파레토 최적 해: study.best_trials


def simulate_training(n_layers, n_units, lr):
    return 0.9  # placeholder

def simulate_accuracy(n_layers, n_units):
    return 0.9  # placeholder

def simulate_latency(n_layers, n_units):
    return 10.0  # placeholder

실전: Scikit-learn + Optuna 통합 파이프라인

import optuna
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import (
    RandomForestClassifier,
    GradientBoostingClassifier
)
from sklearn.svm import SVC
import xgboost as xgb
import lightgbm as lgb

def full_hpo_pipeline():
    """
    모델 선택 + 하이퍼파라미터 최적화를 BO로 통합 수행
    """
    X, y = load_breast_cancer(return_X_y=True)
    cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

    def objective(trial):
        # 모델 선택 자체도 하이퍼파라미터
        model_name = trial.suggest_categorical(
            'model', ['rf', 'gbm', 'xgb', 'lgb', 'svm']
        )

        if model_name == 'rf':
            params = {
                'n_estimators': trial.suggest_int('rf_n_estimators',
                                                   50, 500),
                'max_depth': trial.suggest_int('rf_max_depth', 2, 15),
                'min_samples_split': trial.suggest_int(
                    'rf_min_samples_split', 2, 20
                ),
                'max_features': trial.suggest_categorical(
                    'rf_max_features', ['sqrt', 'log2', None]
                ),
            }
            model = RandomForestClassifier(**params, random_state=42)

        elif model_name == 'gbm':
            params = {
                'n_estimators': trial.suggest_int('gbm_n_estimators',
                                                   50, 500),
                'max_depth': trial.suggest_int('gbm_max_depth', 2, 8),
                'learning_rate': trial.suggest_float(
                    'gbm_lr', 1e-3, 0.3, log=True
                ),
                'subsample': trial.suggest_float('gbm_subsample',
                                                  0.5, 1.0),
            }
            model = GradientBoostingClassifier(**params,
                                               random_state=42)

        elif model_name == 'xgb':
            params = {
                'n_estimators': trial.suggest_int('xgb_n_estimators',
                                                   50, 500),
                'max_depth': trial.suggest_int('xgb_max_depth', 2, 10),
                'learning_rate': trial.suggest_float(
                    'xgb_lr', 1e-3, 0.3, log=True
                ),
                'subsample': trial.suggest_float('xgb_subsample',
                                                  0.5, 1.0),
                'colsample_bytree': trial.suggest_float(
                    'xgb_colsample', 0.5, 1.0
                ),
                'reg_alpha': trial.suggest_float(
                    'xgb_alpha', 1e-8, 10.0, log=True
                ),
                'reg_lambda': trial.suggest_float(
                    'xgb_lambda', 1e-8, 10.0, log=True
                ),
            }
            model = xgb.XGBClassifier(**params, random_state=42,
                                       verbosity=0)

        elif model_name == 'lgb':
            params = {
                'n_estimators': trial.suggest_int('lgb_n_estimators',
                                                   50, 500),
                'max_depth': trial.suggest_int('lgb_max_depth', 2, 10),
                'learning_rate': trial.suggest_float(
                    'lgb_lr', 1e-3, 0.3, log=True
                ),
                'num_leaves': trial.suggest_int('lgb_num_leaves',
                                                 8, 256),
                'min_child_samples': trial.suggest_int(
                    'lgb_min_child', 5, 100
                ),
                'subsample': trial.suggest_float('lgb_subsample',
                                                  0.5, 1.0),
                'colsample_bytree': trial.suggest_float(
                    'lgb_colsample', 0.5, 1.0
                ),
            }
            model = lgb.LGBMClassifier(**params, random_state=42,
                                        verbosity=-1)

        else:  # svm
            params = {
                'C': trial.suggest_float('svm_C', 1e-3, 100, log=True),
                'kernel': trial.suggest_categorical(
                    'svm_kernel', ['rbf', 'poly', 'sigmoid']
                ),
                'gamma': trial.suggest_categorical(
                    'svm_gamma', ['scale', 'auto']
                ),
            }
            model = Pipeline([
                ('scaler', StandardScaler()),
                ('svm', SVC(**params, random_state=42))
            ])

        scores = cross_val_score(model, X, y, cv=cv,
                                 scoring='accuracy')
        return scores.mean()

    study = optuna.create_study(
        direction='maximize',
        sampler=optuna.samplers.TPESampler(
            multivariate=True,  # 파라미터 간 상관관계 모델링
            seed=42
        )
    )
    study.optimize(objective, n_trials=200, show_progress_bar=True)

    print(f"Best model: {study.best_params['model']}")
    print(f"Best accuracy: {study.best_value:.4f}")
    print(f"Best params: {study.best_params}")

    # 시각화
    # optuna.visualization.plot_optimization_history(study)
    # optuna.visualization.plot_param_importances(study)
    # optuna.visualization.plot_parallel_coordinate(study)

    return study

Grid/Random/Bayesian 비교

기준 Grid Search Random Search Bayesian Optimization
탐색 전략 모든 조합 무작위 순차적 모델 기반
평가 효율성 매우 낮음 중간 높음
고차원 적합성 차원의 저주 양호 20D 이하 효과적
병렬화 완전 병렬 완전 병렬 비동기 가능 (batch BO)
조건부 파라미터 지원 안 됨 지원 안 됨 TPE/SMAC 지원
이론적 보장 없음 고정된 중요 차원에서 최적 (Bergstra & Bengio, 2012) GP-UCB의 서브리니어 후회(Srinivas et al., 2010)
적합한 상황 2-3개 파라미터 빠른 베이스라인 평가 비용 높은 경우

프레임워크 비교

프레임워크 Surrogate 언어 특징
Optuna TPE (기본), GP, CMA-ES Python 가장 범용적, define-by-run, pruning 내장
BoTorch / Ax GP (exact & approx) Python Meta 개발, 고급 GP/acquisition, 연구용
SMAC3 Random Forest Python 범주형 강점, algorithm configuration
Hyperopt TPE Python 초기 프레임워크, 분산 지원 (SparkTrials)
Ray Tune 다양 (Optuna, BOHB 등 통합) Python 분산/스케일링 특화, 스케줄러 통합
Weights & Biases Sweeps Bayes, Random, Grid Python 실험 추적 통합

안티패턴

안티패턴 문제 해결
초기 샘플 부족 surrogate 부정확, 조기 수렴 최소 2*d개 초기 샘플 (d: 차원 수)
탐색 범위 과다 대부분의 영역이 무의미 사전 지식으로 범위 축소, log scale 활용
GP에 고차원 적용 O(n^3) 스케일링, curse of dimensionality TPE/SMAC 사용 또는 차원 축소
노이즈 무시 동일 설정에서 다른 결과 -> 잘못된 surrogate CV 기반 평가, 노이즈 파라미터 추정
과도한 exploitation 지역 최적에 수렴 kappa 증가(UCB), xi 증가(EI), 초기 exploration 강화
고정 획득 함수 최적화 단계별 최적 전략이 다름 portfolio 전략 (GP-Hedge), 적응형 전환

핵심 참고 자료

논문/자료 저자 발표 기여
Practical Bayesian Optimization of ML Algorithms Snoek, Larochelle, Adams NeurIPS 2012 GP 기반 BO의 실용적 적용 확립
Algorithms for Hyper-Parameter Optimization Bergstra et al. NeurIPS 2011 TPE 제안, 조건부 탐색 공간
Random Search for Hyper-Parameter Optimization Bergstra & Bengio JMLR 2012 Random Search의 효율성 입증
Taking the Human Out of the Loop Shahriari et al. IEEE 2016 BO 종합 서베이 (5000+ 인용)
A Tutorial on Bayesian Optimization Frazier arXiv 2018 BO 이론 및 실전 튜토리얼
BOHB: Robust and Efficient HPO at Scale Falkner, Klein, Hutter ICML 2018 TPE + HyperBand 결합
Scalable Global Optimization via Local BO (TuRBO) Eriksson et al. NeurIPS 2019 Trust Region 기반 고차원 BO
Understanding High-Dimensional BO Hvarfner et al. arXiv 2025 고차원 BO 도전과제 분석
BoTorch: A Framework for Efficient MC-based BO Balandat et al. NeurIPS 2020 모듈형 BO 프레임워크
Tree-structured Parzen Estimator: Understanding Its Components Watanabe arXiv 2023 TPE 내부 구성요소 심층 분석
Adaptive Kernel Design (CAKE) with LLMs NeurIPS 2025 NeurIPS 2025 LLM 활용 커널 설계
Pre-trained Gaussian Processes (HyperBO) NeurIPS 2024 NeurIPS 2024 사전학습 GP로 cold-start 해결