메인 콘텐츠로 건너뛰기
Colab에서 실행해 보기 원하는 메트릭(예: 모델 정확도)을 만족하는 머신 러닝 모델을 찾는 일은 보통 여러 번 반복해야 하는 번거로운 작업입니다. 상황을 더 어렵게 만드는 것은, 주어진 학습 실행에서 어떤 하이퍼파라미터 조합을 사용해야 할지 명확하지 않을 수 있다는 점입니다. W&B Sweeps를 사용하면 학습률, 배치 크기, 은닉층 수, 옵티마이저 유형 등과 같은 하이퍼파라미터 값 조합을 자동으로 탐색하여, 원하는 메트릭 기준으로 모델을 최적화하는 값을 찾을 수 있는 체계적이고 효율적인 방법으로 검색을 수행할 수 있습니다. 이 튜토리얼에서는 W&B PyTorch 통합을 사용해 하이퍼파라미터 탐색을 설정합니다. 동영상 튜토리얼을 보면서 따라 해 보세요.
하이퍼파라미터 스윕 결과

스위프: 개요

W&B로 하이퍼파라미터 스위프를 실행하는 것은 매우 간단합니다. 다음 3단계만 따르면 됩니다:
  1. 스위프 정의: 검색할 파라미터, 검색 전략, 최적화 지표 등을 지정하는 딕셔너리 또는 YAML 파일을 만들어 스위프를 정의합니다.
  2. 스위프 초기화: 한 줄의 코드로 스위프를 초기화하고, 스위프 설정이 들어 있는 딕셔너리를 전달합니다: sweep_id = wandb.sweep(sweep_config)
  3. 스위프 에이전트 실행: 마찬가지로 한 줄의 코드로 wandb.agent()를 호출하고, 실행할 sweep_id와 함께 모델 아키텍처를 정의하고 학습을 수행하는 함수를 전달합니다: wandb.agent(sweep_id, function=train)

시작하기 전에

W&B를 설치하고 W&B Python SDK를 노트북으로 가져옵니다:
  1. !pip install로 설치합니다:
!pip install wandb -Uq
  1. W&B를 가져옵니다:
import wandb
  1. W&B에 로그인한 다음, 안내에 따라 API key를 입력합니다:
wandb.login()

1단계: Sweep 정의하기

W&B Sweep은 다양한 하이퍼파라미터 값을 시도하는 전략과 해당 값을 평가하는 코드를 결합한 것입니다. Sweep을 시작하기 전에 _sweep 설정_으로 sweep 전략을 정의해야 합니다.
Jupyter Notebook에서 sweep을 시작하는 경우, sweep을 위해 생성하는 sweep 설정은 중첩된 딕셔너리 형태여야 합니다.명령줄에서 sweep을 실행하는 경우, YAML 파일로 sweep 설정을 지정해야 합니다.

검색 방법 선택

먼저 구성 딕셔너리에서 사용할 하이퍼파라미터 검색 방법을 지정합니다. 선택할 수 있는 하이퍼파라미터 검색 전략은 grid, random, Bayesian search의 세 가지입니다. 이 튜토리얼에서는 무작위 검색(random search)을 사용합니다. 노트북에서 딕셔너리를 만들고 method 키에 random 값을 지정하세요.
sweep_config = {
    'method': 'random'
    }
최적화하려는 메트릭을 지정합니다. 랜덤 서치 방식을 사용하는 스윕의 경우 메트릭과 목표를 지정할 필요는 없습니다. 그러나 나중에 참고할 수 있도록 스윕의 목표를 기록해 두는 것이 좋습니다.
metric = {
    'name': 'loss',
    'goal': 'minimize'   
    }

sweep_config['metric'] = metric

탐색할 하이퍼파라미터 지정하기

이제 스윕 구성에서 탐색 방법을 지정했으므로, 어떤 하이퍼파라미터를 탐색할지 지정합니다. 이를 위해 parameter 키에 하나 이상의 하이퍼파라미터 이름을 지정하고, value 키에 해당하는 하나 이상의 하이퍼파라미터 값을 지정합니다. 특정 하이퍼파라미터에 대해 탐색할 값은, 살펴보려는 하이퍼파라미터의 유형에 따라 달라집니다. 예를 들어 머신러닝 옵티마이저를 선택한 경우, Adam 옵티마이저나 확률적 경사 하강법과 같은 하나 이상의 구체적인 옵티마이저 이름을 지정해야 합니다.
parameters_dict = {
    'optimizer': {
        'values': ['adam', 'sgd']
        },
    'fc_layer_size': {
        'values': [128, 256, 512]
        },
    'dropout': {
          'values': [0.3, 0.4, 0.5]
        },
    }

sweep_config['parameters'] = parameters_dict
하이퍼파라미터를 추적하되 값을 변경하지 않고 고정해 두고 싶은 경우가 있을 수 있습니다. 이때는 스윕 설정에 해당 하이퍼파라미터를 추가하고 사용하려는 정확한 값을 지정하면 됩니다. 예를 들어, 다음 코드 셀에서는 epochs가 1로 설정되어 있습니다.
parameters_dict.update({
    'epochs': {
        'value': 1}
    })
random 탐색의 경우, 하나의 실행에서 어떤 파라미터의 모든 values가 동일한 확률로 선택됩니다. 또는, distribution 의 이름과 함께 평균 munormal 분포의 표준편차 sigma 와 같은 파라미터를 지정할 수도 있습니다.
parameters_dict.update({
    'learning_rate': {
        # 0과 0.1 사이의 균등 분포
        'distribution': 'uniform',
        'min': 0,
        'max': 0.1
      },
    'batch_size': {
        # 32에서 256 사이의 정수
        # 로그 균등 분포 적용 
        'distribution': 'q_log_uniform_values',
        'q': 8,
        'min': 32,
        'max': 256,
      }
    })
모든 설정을 마치면 sweep_config는 어떤 parameters를 탐색할지와 이를 탐색하는 데 사용할 method가 무엇인지 정확히 지정하는 중첩된 딕셔너리가 됩니다. 스위프 설정이 어떻게 생겼는지 살펴보겠습니다:
import pprint
pprint.pprint(sweep_config)
전체 구성 옵션 목록은 Sweep configuration options를 참조하세요.
가능한 선택지가 사실상 무한한 하이퍼파라미터의 경우, 일반적으로 선별한 몇 가지 values만 시도해 보는 것이 좋습니다. 예를 들어, 위의 sweep 구성에서는 layer_sizedropout 파라미터 키에 대해 유한한 개수의 값 목록을 지정했습니다.

2단계️: Sweep 초기화

검색 전략을 정의했다면, 이제 이를 구현할 수단을 설정할 차례입니다. W&B는 클라우드 또는 하나 이상의 머신에서 로컬로 sweep을 관리하기 위해 Sweep Controller를 사용합니다. 이 튜토리얼에서는 W&B가 관리하는 Sweep Controller를 사용합니다. Sweep Controller가 sweep을 관리하는 동안, 실제로 sweep을 실행하는 구성 요소는 sweep agent라고 합니다.
기본적으로 Sweep Controller 구성 요소는 W&B의 서버에서 시작되며, sweep을 생성하는 구성 요소인 sweep agent는 로컬 머신에서 활성화됩니다.
노트북 내에서 wandb.sweep 메서드를 사용해 Sweep Controller를 활성화할 수 있습니다. 앞에서 정의한 sweep 구성 딕셔너리를 sweep_config 필드에 전달하십시오:
sweep_id = wandb.sweep(sweep_config, project="pytorch-sweeps-demo")
wandb.sweep 함수는 이후 단계에서 스윕을 활성화할 때 사용할 sweep_id를 반환합니다.
명령줄에서는 이 함수를 대신하여 다음 명령을 사용합니다:
wandb sweep config.yaml
터미널에서 W&B Sweep을 생성하는 방법에 대한 자세한 내용은 W&B Sweep 워크스루를 참고하세요.

3단계: 머신러닝 코드를 정의합니다

스윕을 실행하기 전에 시도해 보고 싶은 하이퍼파라미터 값을 사용하는 학습 절차를 정의합니다. 학습 코드에 W&B Sweeps를 통합하는 핵심은, 각 학습 실험에서 학습 로직이 스윕 구성에서 정의한 하이퍼파라미터 값에 접근할 수 있도록 하는 것입니다. 다음 코드 예제에서 build_dataset, build_network, build_optimizer, train_epoch 헬퍼 함수들은 스윕 하이퍼파라미터 구성 딕셔너리(사전)에 접근합니다. 다음 머신러닝 학습 코드를 노트북에서 실행하십시오. 이 함수들은 PyTorch를 사용해 기본적인 완전연결 신경망을 정의합니다.
import torch
import torch.optim as optim
import torch.nn.functional as F
import torch.nn as nn
from torchvision import datasets, transforms

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def train(config=None):
    # 새로운 wandb 실행 초기화
    with wandb.init(config=config) as run:
        # 아래와 같이 wandb.agent에 의해 호출된 경우,
        # 이 config는 Sweep Controller에 의해 설정됩니다
        config = run.config

        loader = build_dataset(config.batch_size)
        network = build_network(config.fc_layer_size, config.dropout)
        optimizer = build_optimizer(network, config.optimizer, config.learning_rate)

        for epoch in range(config.epochs):
            avg_loss = train_epoch(network, loader, optimizer)
            run.log({"loss": avg_loss, "epoch": epoch})           
train 함수 내부에서 다음과 같은 W&B Python SDK 메서드를 사용합니다:
  • wandb.init(): 새로운 W&B 실행을 초기화합니다. 각 실행은 학습 함수의 단일 실행입니다.
  • run.config: 실험하려는 하이퍼파라미터가 포함된 스윕 구성을 전달합니다.
  • run.log(): 각 에포크에 대한 학습 손실을 기록합니다.
다음 셀은 네 개의 함수를 정의합니다: build_dataset, build_network, build_optimizer, 그리고 train_epoch. 이 함수들은 기본 PyTorch 파이프라인의 표준 구성 요소이며, W&B 사용과 무관하게 구현은 동일합니다.
def build_dataset(batch_size):
   
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.1307,), (0.3081,))])
    # MNIST 학습 데이터셋 다운로드
    dataset = datasets.MNIST(".", train=True, download=True,
                             transform=transform)
    sub_dataset = torch.utils.data.Subset(
        dataset, indices=range(0, len(dataset), 5))
    loader = torch.utils.data.DataLoader(sub_dataset, batch_size=batch_size)

    return loader


def build_network(fc_layer_size, dropout):
    network = nn.Sequential(  # 완전 연결, 단일 은닉층
        nn.Flatten(),
        nn.Linear(784, fc_layer_size), nn.ReLU(),
        nn.Dropout(dropout),
        nn.Linear(fc_layer_size, 10),
        nn.LogSoftmax(dim=1))

    return network.to(device)
        

def build_optimizer(network, optimizer, learning_rate):
    if optimizer == "sgd":
        optimizer = optim.SGD(network.parameters(),
                              lr=learning_rate, momentum=0.9)
    elif optimizer == "adam":
        optimizer = optim.Adam(network.parameters(),
                               lr=learning_rate)
    return optimizer


def train_epoch(network, loader, optimizer):
    cumu_loss = 0

    with wandb.init() as run:
        for _, (data, target) in enumerate(loader):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()

            # ➡ 순전파
            loss = F.nll_loss(network(data), target)
            cumu_loss += loss.item()

            # ⬅ 역전파 + 가중치 업데이트
            loss.backward()
            optimizer.step()

            run.log({"batch loss": loss.item()})

    return cumu_loss / len(loader)
PyTorch에서 W&B를 계측하는 방법에 대한 더 자세한 내용은 이 Colab을 참고하세요.

4단계: 스윕 에이전트 활성화

이제 스윕 설정을 정의했고, 해당 하이퍼파라미터를 동적으로 활용할 수 있는 학습 스크립트도 준비되었으므로, 스윕 에이전트를 활성화할 준비가 되었습니다. 스윕 에이전트는 스윕 설정에서 정의한 하이퍼파라미터 값 집합으로 실험을 실행하는 역할을 담당합니다. wandb.agent 메서드를 호출해 스윕 에이전트를 생성합니다. 다음 값을 전달합니다:
  1. 에이전트가 속한 스윕 (sweep_id)
  2. 스윕이 실행해야 할 함수. 이 예제에서는 스윕이 train 함수를 사용합니다.
  3. (선택 사항) 스윕 컨트롤러에 요청할 설정 개수 (count)
동일한 sweep_id로 여러 스윕 에이전트를 서로 다른 컴퓨팅 리소스에서 시작할 수 있습니다. 스윕 컨트롤러는 여러분이 정의한 스윕 설정에 맞게 이들이 함께 동작하도록 보장합니다.
다음 셀은 학습 함수(train)를 5번 실행하는 스윕 에이전트를 활성화합니다:
wandb.agent(sweep_id, train, count=5)
스윕 설정에서 random 탐색 방식을 지정했기 때문에 스윕 컨트롤러는 무작위로 생성된 하이퍼파라미터 값을 제공합니다.
터미널에서 W&B 스윕을 생성하는 방법에 대한 자세한 내용은 W&B 스윕 워크스루를 참조하세요.

스윕 결과를 시각화하기

병렬 좌표 플롯

이 플롯은 하이퍼파라미터 값을 모델 지표에 매핑합니다. 가장 좋은 모델 성능을 낸 하이퍼파라미터 조합에 집중해 좁혀 나가는 데 유용합니다.
Sweep agent execution results

하이퍼파라미터 중요도 플롯

하이퍼파라미터 중요도 플롯은 어떤 하이퍼파라미터가 메트릭을 가장 잘 예측하는지를 보여줍니다. 랜덤 포레스트 모델에서 계산된 특성 중요도와 상관관계(사실상 선형 모델에 해당)를 함께 제공합니다.
W&B sweep dashboard
이러한 시각화를 사용하면 가장 중요한 하이퍼파라미터와 그 값 범위를 빠르게 파악하여, 비용이 큰 하이퍼파라미터 최적화 실행 시 시간과 리소스를 절약하고 추가 탐색이 필요한 영역에 집중할 수 있습니다.

W&B Sweeps 더 자세히 알아보기

여러분이 바로 실습해 볼 수 있도록, 간단한 학습 스크립트와 여러 가지 Sweep 구성 예시를 준비해 두었습니다. 꼭 한 번 시도해 보시기를 강력히 추천합니다. 해당 리포지터리에는 Bayesian Hyperband, Hyperopt와 같은 더 고급 Sweep 기능을 활용해 볼 수 있도록 도와주는 예제들도 포함되어 있습니다.