본문 바로가기
목차
ML

optuna : Automatic Hyperparameter Optimization Framework

by ds31x 2026. 6. 27.
728x90
반응형

Optuna는

  • 2018년 Preferred Networks에서 공개하고
  • 2019년 논문 Optuna: A Next-generation Hyperparameter Optimization Framework로 소개됨

Machine Learning(기계학습)을 위한
Automatic Hyperparameter Optimization Framework
(자동 하이퍼파라미터 최적화 프레임워크)임.

Optuna는 Hyperparameter Search Space(하이퍼파라미터 탐색 공간) 안에서

  • Learning Rate(학습률), Batch Size(배치 크기), Optimizer(최적화 알고리즘) 종류, Layer 수(층 수), Epoch 수(학습 반복 횟수) 같은 Hyperparameter(하이퍼파라미터) 후보값들을
  • Trial(시도) 단위로 자동 탐색하는
  • Hyperparameter Optimization Framework 임.

https://dsaint31.me/mkdocs_site/ML/ch08/dl_hyperparameters/

 

BME

Activation Function Batch Size Deep Learning Hyperparameter Layer Neuron Optimizer Hyper-Parameters in DL Deep Learning에서 Hyper-parameter는 model이 학습을 통해 자동으로 결정하는 값(= parameter)이 아니라, 학습 전에 사용자가

dsaint31.me


주요 특징

Optuna의 주요 특징은 다음과 같음.

  • Define-by-Run API(실행 기반 정의 API):
    • Hyperparameter Search Space(하이퍼파라미터 탐색 공간)를 고정된 설정 파일이 아니라
      Python Code(파이썬 코드) 안에서 동적으로 정의하는 방식임.
    • 이를 통해 조건에 따라 다른 Hyperparameter(하이퍼파라미터)를 탐색하는
      Conditional Search Space(조건부 탐색 공간) 구성도 가능함.
  • 다양한 Sampler 지원:
    • TPESampler, CmaEsSampler여러 Optimization Algorithm(최적화 알고리즘)을 지원함.
    • 사용자는 문제의 특성에 따라 적절한 Sampler(샘플러)를 선택하여 Hyperparameter(하이퍼파라미터)를 탐색할 수 있음.
  • Pruner(가지치기 도구) 지원:
    • 성능이 좋지 않은 Trial을 학습 도중 조기에 중단하는 기능임.
    • 불필요한 계산을 줄여 Hyperparameter Optimization에 필요한 시간과 자원을 절약할 수 있음.
  • Visualization(시각화) 기능 제공:
    • Plotly 기반의 Visualization(시각화) 기능을 제공함 (Matplotlib 도 가능).
    • Optimization History(최적화 이력), Hyperparameter Importance(하이퍼파라미터 중요도), Parallel Coordinate Plot(평행 좌표 그래프) 등을 통해 탐색 과정을 분석할 수 있음.
  • Distributed Optimization(분산 최적화) 지원:
    • 여러 Process(프로세스) 또는 여러 Machine(머신)에서 동시에 Trial(시도)을 수행할 수 있음.
    • 대규모 Hyperparameter Search(하이퍼파라미터 탐색)를 병렬로 수행할 때 유리함.

2024.03.28 - [Python] - [DL] Define and Run vs. Define by Run

 

[DL] Define and Run vs. Define by Run

Deep Learning (DL) Framework의 동작방식을 비교하는 용어. DL Model의 구축과 실행이 어떻게 이루어지는지로 구분됨. Define and Run DL Model을 구축 (= Computational Graph)이 먼저 이루어지고, 이후 input tesnsor를 정

ds31x.tistory.com


PyTorch, Hugging Face, Scikit Learn

PyTorch에서는

  • 사용자가 objective Function 안에 Training Loop(학습 루프)를 직접 구현하는 구조임.
  • Optuna는 각 Trial(시도)마다 서로 다른 Hyperparameter Combination(하이퍼파라미터 조합)을 제안함.
  • objective Function(목적 함수)은 해당 Trial(시도)의 Hyperparameter(하이퍼파라미터)를 사용하여 Model(모델) 생성, Training(학습), Validation(검증)을 수행함.
  • 이후 objective Function(목적 함수)이 Validation Performance(검증 성능)를 반환함.
  • Optuna는 반환된 Validation Performance(검증 성능)를 기준으로 여러 Trial(시도)을 비교하고, 가장 좋은 Hyperparameter Setting(하이퍼파라미터 설정)을 찾는 데 활용됨.

Hugging Face에서는

  • 사용자가 Training Loop(학습 루프)를 직접 구현하기보다 transformers.Trainer가 제공하는 Training Structure를 사용하는 방식임.
  • Optuna는 transformers.Trainer.hyperparameter_search()Backend(백엔드)로 지정되어
    각 Trial마다 서로 다른 Hyperparameter Combination(하이퍼파라미터 조합)을 제안함.
  • transformers.Trainer는 해당 Trial의 Hyperparameter(하이퍼파라미터)를 사용하여
    Model(모델) 생성, Training(학습), Evaluation(평가)을 수행함.
  • 이후 transformers.Trainer는 Evaluation Metric(평가 지표)을 바탕으로 해당 Trial의 Objective Value를 계산함.
  • Optuna는 반환된 Objective Value를 기준으로 여러 Trial을 비교하고, 가장 좋은 Hyperparameter Setting을 찾는 데 활용됨.

Scikit Learn에서는

  • objective Function 안에서 Scikit Learn Model(사이킷런 모델=estimatro)을 생성하고 학습시키는 구조임.
  • Optuna는 각 Trial마다 서로 다른 Hyperparameter Combination(하이퍼파라미터 조합)을 제안함.
  • objective Function은 해당 Trial의 Hyperparameter를 사용하여
    Model을 생성하고, fit() Method를 통해 Training을 수행함.
  • 이후 Validation Set(검증 세트) 또는 Cross Validation(교차 검증)을 통해
    Validation Performance(검증 성능)를 계산하고 반환함.
  • Optuna는 반환된 Validation Performance(검증 성능)를 기준으로
    여러 Trial을 비교하고, 가장 좋은 Hyperparameter Setting을 찾는 데 활용됨.

최적화 대상이 되는
Hyperparameter가 추가되면
Hyperparameter space가 exponentially 증가함에 유의


주요 구성 요소

주요 구성요소는 다음과 같음

Study

  • Study는 전체 Hyperparameter Search(하이퍼파라미터 탐색) 작업을 추상화한 객체임.
    • 보다 정확히는 Objective Function을 기반으로 한 Hyperparameter Optimization 작업 전체를 의미함.
    • 하나의 Study는 여러 Trial들로 구성됨.
    • 각 Trial은 서로 다른 Hyperparameter Combination(하이퍼파라미터 조합)을 사용하여
      Objective Function을 한 번 실행한 결과임.
  • Study의 Entry Point는 일반적으로 optuna.create_study()임.
    • study = optuna.create_study(direction="minimize")처럼 생성함.
    • 생성시 sampler를 지정할 수도 있으나 기본인 TPESampler 를 굳이 바꾸지 않아도 됨.
    • direction="minimize"Objective Value를 최소화하는 방향의 탐색을 의미함.
    • direction을 생략하면 기본값은 "minimize"임.
  • 생성된 Study는 study.optimize(objective, n_trials=...)를 통해 실행됨.
    • objective Function을 지정한 횟수만큼 반복 실행함.
    • 이때 objective Function의 각 실행이 하나의 Trial에 해당함.
  • 탐색이 끝난 이후에는 Study 객체를 통해 결과를 확인함.
    • study.best_params : 가장 좋은 Hyperparameter Combination(하이퍼파라미터 조합) 확인 (dict).
    • study.best_value : 가장 좋은 Objective Value 확인 (float).
    • study.best_trial : 가장 좋은 Trial 객체 확인 (Trial).
    • study.trials : 전체 Trial 목록 확인 (list).
  • SQLite, MySQL, PostgreSQL 등의 Storage를 사용할 수 있음.
    • 일종의 persistence tool임.
    • 이 경우 Hyperparameter Search(하이퍼파라미터 탐색) 작업을 중단한 뒤 다시 이어서 수행 가능
    • 같은 Storage를 여러 Process 또는 여러 Machine이 공유하면 Distributed Optimization(분산 최적화)에도 활용할 수 있음.
    • Study객체 생성시 study_name 파라미터에 적절한 문자열을 할당하고,
      load_if_exists 파라미터에 True를 할당하면서,
      storage에 적절한 SQL database를 지정하면 됨.
      • study_name 에 같은 이름을 사용하고
      • load_if_exists=True를 지정하면,
      • 이미 존재하는 Study를 다시 불러와 이전 Trial 결과에 이어서 Hyperparameter Search를 계속 수행함.
# SQLite DB를 Storage(저장소)로 사용하는 Study(스터디) 생성.
# 같은 study_name과 storage를 다시 지정하면 기존 Study를 이어서 사용할 수 있음.
study = optuna.create_study(
    study_name="simple_quadratic_search",
    direction="minimize",
    storage="sqlite:///optuna_study.db",
    load_if_exists=True,
)

Trial

  • Trial은 Hyperparameter Search Space(하이퍼파라미터 탐색 공간)에서
    하나의 Hyperparameter Combination을 평가하는 단위임.
  • 하나의 Trial마다 objective Function이 한 번 실행됨.
  • 각 Trial에서는 해당 Hyperparameter Combination을 사용하여 새로운 Model Instance가 생성되고 학습됨.
  • 이후 Validation Set 을 통해 해당 Trial의 성능이 측정됨.
  • 측정된 성능은 Objective Value로 반환되며, Study는 이 값을 기준으로 여러 Trial을 비교함.

뒤에 다룰 Hyperparameter(하이퍼파라미터)의 특성에 따라 다음 Method(메서드)를 통해 탐색 후보를 설정할 수 있음.

  • trial.suggest_categorical(name, choices) : 주어진 목록의 값들 중 하나를 선택함
    • 후보가 명시적으로 정해진 경우 사용됨.
    • 문자열, Boolean, Optimizer 종류(최적화 알고리즘 종류), Activation Function 등
  • trial.suggest_int(name, low, high) : low부터 high까지의 정수 범위 안에서 하나의 값을 선택함.
  • trial.suggest_float(name, low, high) : low부터 high까지의 실수 범위 안에서 하나의 값을 선택함.
  • trial.suggest_float(name, low, high, log=True) : low부터 high까지의 범위를 Log Scale로 보고 값을 선택함.
    • Learning Rate처럼
    • 크기의 자릿수가 중요한 Hyperparameter(하이퍼파라미터)에 주로 사용됨.
  • trial.suggest_float(name, low, high, step=...) : step 간격으로 이산(discrete)화된 실수 후보 중 하나를 선택함.
    • 연속적인 실수 범위가 아니라 일정 간격으로 나뉜 후보값만 탐색하고자 할 때 사용됨.

현재 Optuna에서는 suggest_uniform()suggest_loguniform()보다 suggest_float() 사용이 권장됨.

  • 기존의 trial.suggest_uniform(name, low, high)trial.suggest_float(name, low, high)로,
  • 기존의 trial.suggest_loguniform(name, low, high)trial.suggest_float(name, low, high, log=True)로 대체가 권장됨.

Optuna v3 migration guide 참고

 

Optuna v3 Migration Guide · optuna optuna · Discussion #3930

As Optuna introduces new features and improves existing ones, the changes sometimes make older APIs deprecated. This guide helps you migrate from Optuna v2.x to Optuna v3. Suggest APIs The suggest ...

github.com


Objective

  • Objective Function 은 각 Trial의 성능 비교 기준이 되는 Objective Value(목적 함수 값)를 반환하는 함수임.
  • 실제 Python Function으로 구현되며, Trial 객체를 인자로 받음.
    • 일반적으로 def objective(trial): 형태로 정의함.
    • 인자가 Trial 객체 하나만 가능!!! : functools.partial 등의 highorder function으로 싸거나 lambda 사용이 일반적.
  • 인자로 전달된 Trial 객체를 통해 Hyperparameter Combination을 제안받음.
    • 예: trial.suggest_float(...), trial.suggest_int(...), trial.suggest_categorical(...) 등.
  • 해당 Trial(시도)의 Hyperparameter Combination을 사용하여 새로운 Model Instance를 생성하고 학습시킴.
  • 이후 Validation Set(검증 세트) 또는 Cross Validation(교차 검증)을 통해 해당 Trial의 Validation Performance를 측정함.
  • 측정된 Validation Performance(검증 성능)를 Objective Value(목적 함수 값)로 반환함.
    • 예: Validation Loss(검증 손실), Accuracy(정확도), F1 Score, $R^2$ Score(결정계수) 등.
  • 반환된 Objective Value는 Study가 여러 Trial을 비교하고, 최적의 Hyperparameter Setting을 찾는 기준으로 사용됨.

Hyperparameter

ML에서 Hyperparameter(하이퍼파라미터)는 학습 데이터로부터 자동으로 값이 구해지는 Parameter(파라미터)와 달리,
개발자가 Validation Set(검증 세트)을 통한 성능 비교를 기준으로 적절한 값을 찾아야 하는 설정값임.

 

Optuna에서 다루는 Hyperparameter(하이퍼파라미터)는 실무적으로 크게 다음 2가지로 구분할 수 있음.

  • Model Architecture 관련 Hyperparameter(모델 구조 관련 하이퍼파라미터):
    • 각 Trial(시도)마다 새 Model Instance(모델 인스턴스)를 만들 때 사용되는 값임.
    • 해당 Model(모델)의 Layer 수(층 수), Hidden Size(은닉층 크기), Dropout Probability(드롭아웃 확률) 같은 Architecture(구조) 관련 값을 가리킴.
    • 주로 새로운 Model Instance(모델 인스턴스)를 생성하는 함수에서
      trial.suggest_XXX(...) 호출을 통해 후보 구간을 설정함.
    • Hugging Face에서는 transformers.Trainer 객체를 생성할 때
      model_init Parameter(파라미터)로 넘겨지는 Callable Object(호출 가능 객체)에서 다루어짐.
  • Training Configuration 관련 Hyperparameter(학습 설정 관련 하이퍼파라미터):
    • Learning Rate(학습률), Batch Size(배치 크기), Epoch 수(학습 반복 횟수) 같은 Training Hyperparameter(학습 하이퍼파라미터)를 가리킴.
    • 이 값들은 Hyperparameter Search Space(하이퍼파라미터 탐색 공간)를 구성함.
    • Hugging Face 에서는
      transformers.Trainer 객체에서 .hyperparameter_search() Method(메서드)를 호출하여
      최적의 Hyperparameter(하이퍼파라미터)를 검색할 때 사용됨.
      • 주로 hp_space Parameter(파라미터)에 대한 인자로 넘겨지는 Callable Object(호출 가능 객체)에서 다루어짐.

주의할 점은
Optuna 자체가
Hyperparameter(하이퍼파라미터)를 공식적으로 위 2개 범주로만 구분한다기보다
,

Hugging Face transformers.Trainer와 함께 사용할 때나
PyTorch에 적용할 때
모델 생성과
훈련시키는 과정 등으로
나누어 다루어지기 쉬움을 의미함.

Hugging Face의 경우엔 model_init과 hp_space를 통해 명시적으로 나누어짐.


Pruner (고급)

  • Pruner(가지치기 도구)는 성능이 좋지 않은 Trial을 학습 도중 조기에 중단하는 객체임.
    • 모든 Trial을 끝까지 학습시키지 않고, 중간 성능을 기준으로 가능성이 낮은 Trial을 Early Stopping함.
    • 이를 통해 불필요한 계산을 줄이고 Hyperparameter Optimization에 필요한 시간과 자원을 절약할 수 있음.
  • Pruner는 Trial의 Intermediate Value(중간 성능값)를 기준으로 동작함.
    • objective Function(목적 함수) 안에서 학습 중간 성능을 trial.report(value, step)으로 보고해야 함.
    • value는 해당 step에서의 Validation Loss(검증 손실), Accuracy(정확도), F1 Score(F1 점수) 등이며,
      반드시 objective의 최종 반환값과 동일할 필요는 없지만
      동일한 방향성(최소화/최대화 기준)을 따르는 것이 일반적임.
    • step은 보통 Epoch 번호나 Iteration 번호에 해당함.
  • 중간 성능 보고 이후 trial.should_prune()을 호출하여 Trial의 중단 여부를 확인함.
    • trial.should_prune()True를 반환하면 해당 Trial은 더 이상 유망하지 않다고 판단된 것임.
    • 이 경우 optuna.exceptions.TrialPruned를 발생시켜 해당 Trial을 중단함.
  • 대표적인 Pruner로는 MedianPruner, SuccessiveHalvingPruner, HyperbandPruner 등이 있음.
    • MedianPruner는 같은 step에서 이전 Trial들의 중간값 성능과 현재 Trial의 성능을 비교하여 pruning 여부를 결정함
    • SuccessiveHalvingPruner는 성능이 낮은 Trial을 단계적으로 제거하면서 유망한 Trial에 더 많은 자원을 할당하는 방식임.
    • HyperbandPruner는 Successive Halving을 여러 자원 설정에서 수행하는 방식임.
  • MedianPruner에서 자주 사용하는 주요 인자는 다음과 같음.
    • n_startup_trials:
      • Pruning(가지치기)을 시작하기 전에 무조건 끝까지 실행할 Trial(시도)의 개수임.
      • 해당 초기 Trial이 너무 적으면 비교 기준이 불안정하므로, 일정 개수의 Trial을 먼저 수집하기 위해 사용함.
    • n_warmup_steps:
      • 각 Trial 안에서 Pruning을 시작하기 전에 무조건 진행할 Step의 개수임.
      • 학습 초반 성능은 불안정할 수 있으므로, 몇 Epoch 동안은 Trial을 중단하지 않도록 하는 데 사용함.
    • interval_steps:
      • Pruning 여부를 몇 Step마다 검사할지 지정하는 값임.
      • 예를 들어 interval_steps=2이면 매 step마다 검사하지 않고 2 step 간격으로 검사함.
  • Pruner는 optuna.create_study(pruner=...)의 인자로 지정함.
    • pruner = optuna.pruners.MedianPruner(n_startup_trials=5, n_warmup_steps=3)
    • study = optuna.create_study(direction="minimize", pruner=pruner)

Pruner(가지치기 도구)의 기본 사용 흐름은 다음과 같음.

  1. objective(trial) Function 정의.
  2. 학습 중간마다 Validation Performance(검증 성능) 계산.
  3. trial.report(value, step)으로 중간 성능 보고.
  4. trial.should_prune()으로 중단 여부 확인.
  5. 중단 대상이면 raise optuna.exceptions.TrialPruned() 수행.
  6. 중단 대상이 아니면 학습을 계속 진행하고 최종 Objective Value(목적 함수 값)를 반환함.

Sampler (고급)

  • Sampler는 다음 Trial에서 사용할 Hyperparameter Combination(하이퍼파라미터 조합)을 결정하는 객체임.
  • Study는 Sampler를 사용하여 Hyperparameter Search Space(하이퍼파라미터 탐색 공간) 안에서 어떤 후보값을 다음 Trial로 시도할지 정함.
  • 단순한 Grid Search나 Random Search와 달리, 일부 Sampler는 이전 Trial(들의 결과를 참고하여 더 좋은 후보를 선택함.
  • Optuna의 기본 Sampler(샘플러)는 TPESampler임.
    • TPESampler TPE(Tree-structured Parzen Estimator, 트리 구조 파르젠 추정기)를 사용하는 Sampler임.
    • 이전 Trial들의 Objective Value를 바탕으로
      좋은 성능이 나올 가능성이 높은 Hyperparameter(하이퍼파라미터) 영역을 확률적으로 추정함:
      Sequtntial Model-based Optimization Algorithm.
    • 이런 점에서 TPESamplerBayesian Optimization(베이지안 최적화) 계열의 Sampler로 볼 수 있음.
  • 필요한 경우 RandomSampler, GridSampler, CmaEsSampler 등 다른 Sampler(샘플러)를 지정할 수 있음.
  • Sampler는 optuna.create_study(sampler=...)의 인자로 지정함.
import optuna

sampler = optuna.samplers.TPESampler(seed=23)

study = optuna.create_study(
    direction="minimize",
    sampler=sampler,
)

 

재현성을 위한 난수 조절

  • PyTorch, Hugging Face 나 Scikit Learn 등을 사용할 경우 재현성을 위한 이들 각각의 Seed 설정이 필요.
  • PyTorch를 사용할 경우 torch.manual_seed(23), torch.cuda.manual_seed_all(23) 등을 통해 Model Initialization(모델 초기화), Data Shuffling(데이터 셔플링) 등의 난수성을 제어
  • Hugging Face transformers.Trainer를 사용할 경우 transformers.set_seed(23) 또는 transformers.TrainingArguments(seed=42, data_seed=23) 등을 함께 지정
  • random.seed(23), np.random.seed(23) 등도 추천

GPU 연산이나 병렬 처리까지 포함하면
seed를 고정해도 완전한 재현성이 항상 보장되지는 않음에 유의할 것.


Example

Install

2026년 현재 colab에서 사용하려면 설치해야 함.

pip install optuna

Objective, Trial, and Study 이해

Optuna 공식 사이트의 Code Examples에서 제시한 가장 간단한 예제임:

  • objective Function에서 trial.suggest_float()로 $x$(ML에서의 Hyperparameter)의 탐색 범위를 정의,
  • study.optimize()로 100개의 Trial을 수행하여
  • $(x - 2)^2$ (각 Trial의 cost)를 최소화하는 $x$ 값을 찾는 예임.

https://optuna.org/#code_examples

 

Optuna - A hyperparameter optimization framework

Optuna is an automatic hyperparameter optimization software framework, particularly designed for machine learning. It features an imperative, define-by-run style user API.

optuna.org

import optuna  # Optuna package를 import함.

def objective(trial):
    """
    하나의 Trial(시도)에서 수행할 Objective Function(목적 함수)을 정의함.

    이 함수는 Trial 객체를 인자로 받아 Hyperparameter Search Space
    (하이퍼파라미터 탐색 공간)를 정의하고, 해당 Trial의 성능값을 반환함.
    """

    # Trial(시도)마다 x라는 Hyperparameter(하이퍼파라미터)를 -10부터 10 사이의 float 값으로 제안함.
    x = trial.suggest_float("x", -10, 10)

    # Optuna가 최소화할 Objective Value(목적 함수 값)를 반환함.
    # 여기서는 x가 2에 가까울수록 값이 작아지므로, 최적값은 x = 2 근처가 됨.
    return (x - 2) ** 2


# 하나의 Hyperparameter Optimization 작업 전체를 관리하는 Study(스터디)를 생성함.
# direction을 지정하지 않으면 기본값은 "minimize"임.
study = optuna.create_study() # study = optuna.create_study(direction="minimize")

# # SQLite DB를 Storage(저장소)로 사용하는 Study(스터디) 생성.
# # 같은 study_name과 storage를 다시 지정하면 기존 Study를 이어서 사용할 수 있음.
# study = optuna.create_study(
#     study_name="simple_quadratic_search",
#     direction="minimize",
#     storage="sqlite:///optuna_study.db",
#     load_if_exists=True,
# )

# objective 함수를 100번 실행하여 100개의 Trial(시도)을 수행함.
# 각 Trial에서는 서로 다른 x 후보값을 시도하고, 반환된 Objective Value를 기록함.
study.optimize(objective, n_trials=100)

# 전체 Trial 중 가장 좋은 Objective Value를 만든 Hyperparameter 조합을 확인함.
study.best_params  # 예: {"x": 2.002108042}
  • Study는 하나의 Hyperparameter Optimization 작업 전체를 관리하며,
    여러 Trial의 결과와 최적의 Hyperparameter를 저장하는 객체임.
  • Trial은 하나의 Hyperparameter Combination을 사용하여 objective Function을 한 번 실행하는 단위임.
  • Objective Function은 Trial마다 Hyperparameter를 제안받아 성능값을 계산하고,
    Optuna가 최소화 또는 최대화할 Objective Value를 반환하는 함수임.

Scikit Learn의 예

import optuna

from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.neural_network import MLPClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler


# Dataset(데이터셋) 로드
X, y = load_iris(return_X_y=True)


def make_model(trial):
    """
    Trial(시도)마다 Model Architecture(모델 구조) 관련
    Hyperparameter(하이퍼파라미터)를 제안받아
    새로운 Model Instance(모델 인스턴스)를 생성함.
    """

    # Hidden Layer 수(은닉층 수)를 선택함.
    n_layers = trial.suggest_int("n_layers", 1, 3)

    # 각 Hidden Layer(은닉층)의 Unit 수(유닛 수)를 선택함.
    hidden_units = trial.suggest_int("hidden_units", 16, 128)

    # 모든 Hidden Layer(은닉층)가 같은 Unit 수(유닛 수)를 가지는 구조로 설정함.
    hidden_layer_sizes = tuple([hidden_units] * n_layers)

    # Activation Function(활성화 함수)을 선택함.
    activation = trial.suggest_categorical(
        "activation",
        ["relu", "tanh"],
    )

    # L2 Regularization(정규화) 계수 alpha를 선택함.
    alpha = trial.suggest_float(
        "alpha",
        1e-5,
        1e-1,
        log=True,
    )

    # Initial Learning Rate(초기 학습률)를 선택함.
    learning_rate_init = trial.suggest_float(
        "learning_rate_init",
        1e-4,
        1e-1,
        log=True,
    )

    # MLPClassifier는 Feature Scale(특성 스케일)에 민감하므로 StandardScaler와 함께 Pipeline으로 구성함.
    model = make_pipeline(
        StandardScaler(),
        MLPClassifier(
            hidden_layer_sizes=hidden_layer_sizes,
            activation=activation,
            alpha=alpha,
            learning_rate_init=learning_rate_init,
            max_iter=1000,
            random_state=42,
        ),
    )

    return model


def objective(trial):
    """
    하나의 Trial(시도)에 대한 Objective Function(목적 함수).

    make_model(trial)을 통해 Trial별 Model(모델)을 생성하고,
    Cross Validation(교차 검증)을 통해 Validation Performance(검증 성능)를 계산한 뒤,
    Optuna가 최대화할 Objective Value(목적 함수 값)를 반환함.
    """

    # Trial별 Hyperparameter(하이퍼파라미터)가 반영된 Model(모델) 생성
    model = make_model(trial)

    # Cross Validation(교차 검증)을 통해 Validation Performance(검증 성능) 계산
    scores = cross_val_score(
        model,
        X,
        y,
        cv=5,
        scoring="accuracy",
    )

    # Optuna가 maximize할 Objective Value(목적 함수 값) 반환
    return scores.mean()


# Accuracy(정확도)를 최대화하는 Study(스터디) 생성
study = optuna.create_study(direction="maximize")

# objective 함수를 50번 실행하여 50개의 Trial(시도)을 수행
study.optimize(objective, n_trials=50)

# 가장 좋은 Hyperparameter Combination(하이퍼파라미터 조합) 확인
print("Best params:", study.best_params)

# 가장 좋은 Validation Performance(검증 성능) 확인
print("Best score:", study.best_value)

Pruner 예제

import optuna


def objective(trial):
    """
    하나의 Trial(시도)에 대해 실행될 Objective Function(목적 함수).

    Optuna는 이 objective 함수를 Trial(시도)마다 한 번씩 호출함.
    이 함수 안에서 Hyperparameter(하이퍼파라미터)를 제안받고,
    해당 Hyperparameter(하이퍼파라미터)를 사용한 학습 및 검증 과정을 수행한 뒤,
    Study(스터디)가 최소화 또는 최대화할 Objective Value(목적 함수 값)를 반환함.
    """

    # 이번 Trial(시도)에서 사용할 Hyperparameter(하이퍼파라미터) x를 제안받음.
    # x는 -10부터 10 사이의 float 값 중 하나로 선택됨.
    # 실제 ML 예제라면 learning_rate, dropout, hidden_size 등에 해당하는 부분임.
    x = trial.suggest_float("x", -10, 10)

    # 실제 ML 학습에서는 보통 여러 epoch 동안 학습을 반복함.
    # 여기서는 Pruner(가지치기 도구)의 동작을 설명하기 위해
    # 10번의 epoch가 있다고 가정함.
    for epoch in range(10):

        # 실제 ML 학습에서는 이 위치에서 다음 작업이 수행됨.
        # 1. model.train()으로 학습 모드 전환
        # 2. train_loader를 사용하여 1 epoch 학습
        # 3. model.eval()로 평가 모드 전환
        # 4. validation set에 대한 validation loss 계산
        #
        # 여기서는 실제 모델 학습 대신,
        # x가 2에 가까울수록 loss가 작아지는 가상의 validation_loss를 사용함.
        validation_loss = (x - 2) ** 2 + (10 - epoch) * 0.01

        # 현재 epoch에서 얻은 Intermediate Value(중간 성능값)를
        # Optuna의 Pruner(가지치기 도구)에 보고함.
        #
        # 첫 번째 인자 validation_loss:
        #   현재 step에서의 중간 성능값.
        #
        # 두 번째 인자 step=epoch:
        #   중간 성능값이 측정된 시점.
        #   보통 epoch 번호 또는 iteration 번호를 사용함.
        #
        # direction="minimize"인 Study(스터디)에서는
        # validation_loss가 작을수록 좋은 Trial(시도)로 간주됨.
        trial.report(validation_loss, step=epoch)

        # 지금까지 보고된 중간 성능값을 기준으로
        # 현재 Trial(시도)을 조기 중단할지 여부를 Pruner(가지치기 도구)에 물어봄.
        #
        # should_prune()이 True를 반환한다는 것은
        # 현재 Trial(시도)이 이전 Trial(시도)들과 비교했을 때
        # 더 이상 유망하지 않다고 판단되었다는 의미임.
        if trial.should_prune():

            # TrialPruned 예외를 발생시키면
            # Optuna는 현재 Trial(시도)을 실패가 아니라
            # "pruned", 즉 조기 중단된 Trial(시도)로 기록함.
            #
            # 이 Trial(시도)은 끝까지 실행되지 않으며,
            # 남은 epoch에 대한 계산 비용을 절약할 수 있음.
            raise optuna.exceptions.TrialPruned()

    # Pruning(가지치기)되지 않고 마지막 epoch까지 도달한 경우,
    # 최종 Objective Value(목적 함수 값)를 반환함.
    #
    # Study(스터디)는 이 값을 기준으로 Trial(시도)들을 비교함.
    # direction="minimize"이므로 이 값이 작을수록 좋은 Trial(시도)임.
    return (x - 2) ** 2


# MedianPruner(중앙값 기반 가지치기 도구)를 생성함.
# MedianPruner는 같은 step에서 이전 Trial(시도)들의 중간 성능값 중앙값과
# 현재 Trial(시도)의 중간 성능값을 비교하여 pruning 여부를 결정함.
pruner = optuna.pruners.MedianPruner(

    # n_startup_trials:
    # 처음 5개의 Trial(시도)은 pruning하지 않고 끝까지 실행함.
    #
    # 이유:
    # Pruner(가지치기 도구)가 비교 기준으로 사용할
    # 이전 Trial(시도)의 성능 데이터가 어느 정도 필요하기 때문임.
    n_startup_trials=5,

    # n_warmup_steps:
    # 각 Trial(시도) 안에서 처음 3 step까지는 pruning하지 않음.
    #
    # 이유:
    # 학습 초반의 validation loss는 불안정할 수 있으므로,
    # 너무 이른 시점에 Trial(시도)을 중단하지 않기 위함임.
    n_warmup_steps=3,

    # interval_steps:
    # pruning 여부를 몇 step마다 검사할지 지정함.
    #
    # interval_steps=1이면 매 step마다 pruning 여부를 검사함.
    # interval_steps=2이면 2 step마다 한 번씩 검사함.
    interval_steps=1,
)


# Study(스터디)를 생성함.
# Study(스터디)는 전체 Hyperparameter Optimization(하이퍼파라미터 최적화)
# 작업을 관리하는 객체임.
study = optuna.create_study(

    # direction="minimize":
    # objective 함수가 반환하는 Objective Value(목적 함수 값)를
    # 최소화하는 방향으로 탐색함.
    #
    # 여기서는 validation_loss 또는 (x - 2) ** 2가 작을수록 좋으므로
    # minimize를 사용함.
    direction="minimize",

    # 위에서 생성한 Pruner(가지치기 도구)를 Study(스터디)에 연결함.
    # 이 Study(스터디)에서 실행되는 Trial(시도)들은
    # trial.report()와 trial.should_prune()을 통해 pruning 대상이 될 수 있음.
    pruner=pruner,
)


# objective 함수를 100번 실행하여 100개의 Trial(시도)을 수행함.
# 각 Trial(시도)은 서로 다른 x 값을 제안받아 objective 함수를 실행함.
#
# 성능이 좋지 않다고 판단된 Trial(시도)은
# 10 epoch를 끝까지 수행하지 않고 중간에 pruning될 수 있음.
study.optimize(objective, n_trials=100)


# 전체 Trial(시도) 중 가장 좋은 Hyperparameter Combination(하이퍼파라미터 조합)을 출력함.
print("Best params:", study.best_params)

# 전체 Trial(시도) 중 가장 좋은 Objective Value(목적 함수 값)를 출력함.
print("Best value:", study.best_value)

# Study(스터디)에 기록된 전체 Trial(시도)의 개수를 출력함.
# 여기에는 완료된 Trial(시도)과 pruning된 Trial(시도)가 모두 포함됨.
print("Number of trials:", len(study.trials))
  • Pruner(가지치기 도구)는 특히 epoch 단위로 Validation Loss(검증 손실)나 Accuracy(정확도)를 확인할 수 있는 PyTorch 학습 루프에서 유용함.
  • Hugging Face transformers.Trainer.hyperparameter_search()에서도 Optuna backend를 사용할 때 pruning 기능을 함께 활용할 수 있음.

같이 보면 좋은 자료들

https://optuna.readthedocs.io/en/stable/tutorial/index.html

 

Tutorial — Optuna 4.9.0 documentation

© Copyright 2018, Optuna Contributors.

optuna.readthedocs.io

https://optuna.readthedocs.io/en/stable/tutorial/10_key_features/003_efficient_optimization_algorithms.html

 

Efficient Optimization Algorithms — Optuna 4.9.0 documentation

© Copyright 2018, Optuna Contributors.

optuna.readthedocs.io

https://optuna.readthedocs.io/en/stable/reference/generated/optuna.pruners.MedianPruner.html

 

optuna.pruners.MedianPruner — Optuna 4.9.0 documentation

© Copyright 2018, Optuna Contributors.

optuna.readthedocs.io

 

728x90