Loading [MathJax]/jax/output/CommonHTML/jax.js
본문 바로가기
Tools

WandB 사용 예시

by 박서현 2022. 10. 4.

머신러닝 실험 관리의 필요성

머신러닝 모델을 학습하기 위해서 설정해야 하는 변수는 한두 개가 아닙니다. 학습률이나 모멘텀처럼 연속적인 숫자는 이론 상 시도할 수 있는 경우의 수가 무한입니다. 게다가 옵티마이저, 손실함수 등을 여러가지 적용해본다면 실험은 더욱 복잡해지고, 개별 실험을 기록하고 비교하는 과정은 만만치 않을 것입니다.

출처 :  https://pebpung.github.io/wandb/2021/10/06/WandB-1.html

 

머신러닝 실험 관리가 용이하도록 도와주는 툴은 많이 있습니다. 입문하는 과정에서 자주 들어볼 법한 시각화 툴로는 텐서보드TensorBoard가 있습니다. 이외에도 넵튠, WandB은 머신러닝 실험을 위한 대시보드 시각화, 파라미터 튜닝 자동화 등 다양한 기능을 제공합니다. 링크에는 15가지 머신러닝 관리 툴을 소개합니다.

 

WandB

WandB는 머신러닝 실험 관리 툴로 다음과 같은 특징이 있습니다.

  • 무료 : 무료 버전은 개인 프로젝트만 관리할 수 있다. 100GB의 저장 공간을 지원해주고, Private 혹은 Public으로 관리할 수 있습니다.
  • Web UI : 웹 브라우저에서 모든 기능을 이용할 수 있습니다.

WandB에서 제공하는 기능은 크게 5가지입니다.

  • Experiments : 학습 실험의 경과를 추적하고 로그를 남깁니다.
  • Arfifacts : 데이터셋이나 모델의 버전을 관리합니다.
  • Tables : 여러 실험 결과를 테이블로 정리해 비교할 수 있습니다.
  • Sweeps : 여러가지 설정 값을 시도하면서 모델을 최적화합니다.
  • Reports : 실험 리포트를 작성할 수 있습니다. 대시보드를 쉽게 불러올 수 있어 효과적입니다. 팀 단위로 프로젝트를 진행하는 경우 동료와 실험 내용을 공유할 수 있습니다.본 글에서는 Weights & Biases를 소개하고 Experiments와 Sweep의 기초 사용법을 설명합니다. 공식 Quick Start 가이드는 여기에서 확인하시길 바랍니다.

 

Experiments Tracking

wandb 회원가입을 하고 아래 가이드를 봐주세요.

Set Up Wandb

  1. Login
# Command line
pip install wandb
wandb login
# Notebook
import wandb
wandb.login()

작업 환경에서 wandb 라이브러리를 설치하고 로그인합니다. 이후 https://wandb.ai/authorize 혹은 아래 이미지처럼 설정의 API Key를 복사/붙여넣기 합니다.

Start a new run

import wandb
wandb.init(entity="username", # 사용자 이름
           project="my-project", # 프로젝트 이름
           name="test") # run 이름

학습을 시작하기에 앞서 작업wandbrun을 초기화initialize 해야 하고, 실험 결과를 넘길 사용자, 프로젝트 등을 입력해야 합니다. 추가로 실험run의 이름을 name 파라미터로 지정할 수 있습니다. 이외에도 다양한 추가 설정이 있으니, wandb 공식 설명을 참고하길 바랍니다.

Configuration

wandb.init(config={"epochs": 4, "batch_size": 32})
# later
wandb.config.update({"lr": 0.1, "channels": 16})
# argparse.Namespace Configuration
wandb.init()

parser = argparse.ArgumentParser()
parser.add_arguemnt('-e', '--epochs', type=int, default=10)
parser.add_argument('-b', '--batch-size', type=int, default=8, metavar='N',
                     help='input batch size for training (default: 8)')
parser.add_argument('-l', '--learning-rate', type=float, default=1e-4)
args = parser.parse_args()

wandb.config.update(args) # adds all of the arguments as config variables

모델 학습할 때 설정 값을 추적하기 위해 Configuration을 등록해야 합니다. 등록한 Configuration은 웹 UI의 Overview나 테이블에서 확인할 수 있고, 주로 모델을 구분하거나 비교할 때 사용합니다. 설정 변수와 값을 파이썬 dictionary나 argparser Namespace로 정의해 wandb.init이나 wandb.config를 이용해 등록할 수 있습니다. .py 파일을 실행할 때는 argparse를 이용하고, notebook에서는 dictionary를 이용하는 것이 좋습니다.

Track Metrics

wandb.log({
    "Step": global_step,
    "train_l1_loss": train_l1_loss,
    "train sync loss": train_sync_loss,
    "train perceptual loss": train_perceptual_loss,
    "train disc_real_loss": train_disc_real_loss,
    "valid_l1_loss": valid_l1_loss,
    "valid sync loss": valid_sync_loss,
    "valid perceptual loss": valid_perceptual_loss,
    "valid disc_real_loss": valid_disc_real_loss
})

모델 학습 중 손실 함숫값, 정확도 등 다양한 지표를 활용해 학습 진행 상황을 살펴봅니다. wandb의 log 기능을 이용해 간단하게 여러 정보를 지정된 사용자의 프로젝트로 넘길 수 있으며, 웹 UI에 자동으로 실시간 대시보드를 생성합니다.

학습 코드 예시

**# 작동하지 않는 Pytorch pseudocode입니다.**
import argparse
import wandb
import torch

parser = argparse.ArgumentParser()
parser.add_arguemnt('-e', '--epochs', type=int, default=10)
parser.add_argument('-b', '--batch-size', type=int, default=8, metavar='N',
                     help='input batch size for training (default: 8)')
parser.add_argument('-l', '--learning-rate', type=float, default=1e-4)
args = parser.parse_args()

**# wandb initilization : Start a new run**
**wandb.init(entity='username', 
					 project='my-project',
					 run='test-run')
# wandb configuration
wandb.config.update(args)** # adds all of the arguments as config variables

model = MyModel()
optimizer = Adam()
loss_fn = CrossEntropy()

for epoch in range(args.epochs):
    # Train
    running_loss = 0
    log_dict = {}
    for inputs, targets in train_loader:
        outputs = model(inputs)
        train_loss = loss_fn(ouptuts, targets)

        optimizer.zero_grad()
        train_loss.backward()
        optimizer.step()

        running_loss += float(train_loss)

    log_dict['step'] = epoch
    log_dict['train loss'] = running_loss / len(train_loader.dataset)

    # Validation
    if epoch % 5 == 0:
        running_loss = 0
        acc = []
        for inputs, targets in test_loader:
            with torch.no_grad():
                outputs = model(inputs)
                valid_loss = loss_fn(outputs, targets)
            running_loss += float(valid_loss)
            acc.append((outputs.argmax(1) == targets))
    acc = torch.cat(acc)
    acc = acc.sum() / acc.numel()
    log_dict['valid loss'] = running_loss / len(test_loader.dataset)
    log_dict['accuracy'] = acc = acc.sum() / acc.numel()

    # wandb log : track metrics
    wandb.log(log_dict)

Sweep 하이퍼 파라미터 튜닝 자동화

세부 설정 가이드는 공식 문서를 참고하시길 바랍니다.

Jupyter Notebook

아래 코드는 jupyter notebook에서 sweep하는 예시입니다.

**# 작동하지 않는 Pytorch pseudocode입니다.**
import wandb
import torch

def get_loader(config):
		# your data loader getting code here
		return train_loader, test_loader

def get_model(config):
		# your model making code here
		return model

def get_optim(config):
		# your optimizer getting code here
		return optimizer

def train(model, loader, optimizer):
		# your model training code here
		return loss

def validation(model, loader):
		# your model validation code here
		return loss

def main(): # no arguments
    with wandb.init() as run:
        config = wandb.config
        print("epochs :", config.epochs)
        print("learning_rate :", config.learning_rate)
        train_loader, test_loader = get_loader(config)
        model = get_model(config)
        optimizer = get_optim(config)
        for epoch in range(config["epochs"]):
            train_loss = train(model, loader, optimizer) 
            valid_loss = validation(model, loader) 
            wandb.log({"train loss": train_loss,
					   "valid loss": valid_loss,
					   "epoch": epoch})

sweep_config = {
  "name" : "my-sweep",
  "method" : "bayes",
	"metric" : {
		"name": "valid loss"
	  "goal": "minimize"
	}
  "parameters" : {
    "epochs" : {
      "values" : [10, 20, 50]
    },
    "learning_rate" :{
      "min": 0.0001,
      "max": 0.1
    }
  }
}

sweep_id = wandb.sweep(sweep_config)
wandb.agent(sweep_id,
			function=main, # 학습 함수
            count=5, # number of runs to execute
            entity='username', 'project='my-project') # entity, project를 wandb.sweep에 입력합니다.

여기서는 bayes search로 val_loss를 최소화minimize하는 파라미터epoch,learningrate 조합 도출을 시도합니다. epoch은 10, 20, 50 중에 하나를, 학습률은 0.0001과 0.1 사이의 값을 선택해 조합합니다.

💡 참고
GPU를 사용할 때 Jupyter notebook 환경과 함께 wandb.agent를 사용하시면 수행 중 멈출 수 있습니다.
프레임워크에 의한 GPU/CUDA 리소스 초기화 방식 때문에 wandb.agent 및 jupyter 환경에 나쁜 상호 작용이 있을 수 있습니다
임시 해결책으로 에이전트 실행을 위해 python 인터페이스를 사용하지 않는 것입니다. 대신, 스윕 구성에서 program 키를 설정하여 명령줄 인터페이스를 사용하고 다음을 notebook에서 수행합니다

Yaml file

작성 중