메인 콘텐츠로 건너뛰기
Colab에서 실행해 보기 W&B를 사용해 머신러닝 실험 추적, 모델 체크포인트 관리, 팀과의 협업 등을 수행할 수 있습니다. 이 노트북에서는 간단한 PyTorch 모델을 사용해 머신러닝 실험을 생성하고 추적합니다. 노트북을 마치면 팀의 다른 구성원과 공유하고 맞춤 구성할 수 있는 대화형 Project 대시보드를 갖게 됩니다. 여기에서 예시 대시보드를 확인하세요.

사전 준비

W&B Python SDK를 설치한 뒤 로그인하세요:
!pip install wandb -qU
# W&B 계정에 로그인
import wandb
import random
import math
wandb.login()

W&B로 머신 러닝 실험을 시뮬레이션하고 추적하기

머신 러닝 실험을 생성하고, 추적하고, 시각화합니다. 다음 단계를 따르세요:
  1. 실행을 초기화한 뒤, 추적하려는 하이퍼파라미터를 인자로 전달합니다.
  2. 학습 루프 내에서 정확도, 손실과 같은 지표를 기록합니다.
import wandb
import random

project="basic-intro"
config = {
    "learning_rate": 0.02,
    "architecture": "CNN",
    "dataset": "CIFAR-100",
    "epochs": 10,
}

with wandb.init(project=project, config=config) as run:
  # 이 블록은 메트릭을 로깅하는 학습 루프를 시뮬레이션합니다
  epochs = 10
  offset = random.random() / 5
  for epoch in range(2, epochs):
      acc = 1 - 2 ** -epoch - random.random() / epoch - offset
      loss = 2 ** -epoch + random.random() / epoch + offset

      # 2️. 스크립트에서 W&B로 메트릭 로깅
      run.log({"acc": acc, "loss": loss})    
W&B 프로젝트에서 머신 러닝 모델의 성능을 확인합니다. 이전 셀에서 출력된 URL 링크를 복사해서 붙여넣으세요. 이 URL은 모델 성능을 그래프로 시각화한 대시보드를 포함한 W&B 프로젝트로 이동합니다. 다음 이미지는 대시보드 예시입니다:
W&B experiment tracking dashboard
이제 W&B를 의사(pseudo) 머신 러닝 학습 루프에 통합하는 방법을 알았으니, 기본적인 PyTorch 신경망을 사용하여 머신 러닝 실험을 추적해 보겠습니다. 다음 코드는 모델 체크포인트를 W&B에 업로드하여, 조직 내 다른 팀과도 공유할 수 있도록 합니다.

PyTorch를 사용하여 머신 러닝 실험 추적하기

다음 코드 셀은 간단한 MNIST 분류기를 정의하고 학습합니다. 학습하는 동안 W&B가 URL을 출력하는 것을 보게 됩니다. Project 페이지 링크를 클릭하면 결과가 W&B 프로젝트로 실시간으로 전송되는 것을 확인할 수 있습니다. W&B 실행은 지표, 시스템 정보, 하이퍼파라미터, 터미널 출력을 자동으로 로깅하며, 모델 입력과 출력이 포함된 대화형 테이블도 확인할 수 있습니다.

PyTorch Dataloader 설정

다음 셀은 머신 러닝 모델을 학습할 때 필요한 몇 가지 유용한 함수를 정의합니다. 이 함수들은 W&B에 고유한 것이 아니므로 여기에서는 자세히 다루지 않습니다. forward 및 backward 학습 루프를 정의하는 방법, 학습에 사용할 데이터를 로드하기 위해 PyTorch DataLoader를 사용하는 방법, 그리고 torch.nn.Sequential 클래스를 사용해 PyTorch 모델을 정의하는 방법에 대해서는 PyTorch 문서를 참고하세요.
import wandb
import torch, torchvision
import torch.nn as nn
from torchvision.datasets import MNIST
import torchvision.transforms as T

MNIST.mirrors = [
    mirror for mirror in MNIST.mirrors if "http://yann.lecun.com/" not in mirror
]

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


def get_dataloader(is_train, batch_size, slice=5):
    "학습 데이터로더 가져오기"
    full_dataset = MNIST(
        root=".", train=is_train, transform=T.ToTensor(), download=True
    )
    sub_dataset = torch.utils.data.Subset(
        full_dataset, indices=range(0, len(full_dataset), slice)
    )
    loader = torch.utils.data.DataLoader(
        dataset=sub_dataset,
        batch_size=batch_size,
        shuffle=True if is_train else False,
        pin_memory=True,
        num_workers=2,
    )
    return loader


def get_model(dropout):
    "간단한 모델"
    model = nn.Sequential(
        nn.Flatten(),
        nn.Linear(28 * 28, 256),
        nn.BatchNorm1d(256),
        nn.ReLU(),
        nn.Dropout(dropout),
        nn.Linear(256, 10),
    ).to(device)
    return model


def validate_model(model, valid_dl, loss_func, log_images=False, batch_idx=0):
    "검증 데이터셋에서 모델 성능을 계산하고 wandb.Table에 기록"
    model.eval()
    val_loss = 0.0
    with torch.inference_mode():
        correct = 0
        for i, (images, labels) in enumerate(valid_dl):
            images, labels = images.to(device), labels.to(device)

            # 순전파 ➡
            outputs = model(images)
            val_loss += loss_func(outputs, labels) * labels.size(0)

            # 정확도 계산 및 누적
            _, predicted = torch.max(outputs.data, 1)
            correct += (predicted == labels).sum().item()

            # 대시보드에 이미지 한 배치를 기록, 항상 동일한 batch_idx 사용.
            if i == batch_idx and log_images:
                log_image_table(images, predicted, labels, outputs.softmax(dim=1))
    return val_loss / len(valid_dl.dataset), correct / len(valid_dl.dataset)

예측값과 실제 값을 비교하는 테이블 생성하기

다음 셀은 W&B에만 있는 내용이므로, 한 번 짚고 넘어가겠습니다. 이 셀에서는 log_image_table이라는 함수를 정의합니다. 엄밀히 말하면 선택 사항이지만, 이 함수는 W&B Table 객체를 생성합니다. 우리는 이 Table 객체를 사용해 각 이미지에 대해 모델이 무엇을 예측했는지 보여주는 테이블을 만들 것입니다. 좀 더 구체적으로, 각 행에는 모델에 입력된 이미지와 함께 예측값, 그리고 실제 값(레이블)이 포함됩니다.
def log_image_table(images, predicted, labels, probs):
    "Log a wandb.Table with (img, pred, target, scores)"
    # 이미지, 레이블, 예측값을 기록할 wandb Table 생성
    table = wandb.Table(
        columns=["image", "pred", "target"] + [f"score_{i}" for i in range(10)]
    )
    for img, pred, targ, prob in zip(
        images.to("cpu"), predicted.to("cpu"), labels.to("cpu"), probs.to("cpu")
    ):
        table.add_data(wandb.Image(img[0].numpy() * 255), pred, targ, *prob.numpy())

    with wandb.init() as run:
        run.log({"predictions_table": table}, commit=False)

모델을 학습하고 체크포인트 업로드하기

다음 코드는 모델을 학습하고 체크포인트를 프로젝트에 저장합니다. 모델 학습 중 성능을 평가할 때에는 평소와 동일한 방식으로 모델 체크포인트를 사용하면 됩니다. W&B를 사용하면 팀이나 조직 내 다른 구성원과 저장된 모델 및 모델 체크포인트를 쉽게 공유할 수 있습니다. 팀 외부 구성원과 모델 및 모델 체크포인트를 공유하는 방법은 W&B Registry를 참고하세요.
import wandb

config = {
    "epochs": 5,
    "batch_size": 128,
    "lr": 1e-3,
    "dropout": random.uniform(0.01, 0.80),
}

project = "pytorch-intro"

# wandb 실행 초기화
with wandb.init(project=project, config=config) as run:

    # 선택적으로 config 복사
    config = run.config

    # 데이터 가져오기
    train_dl = get_dataloader(is_train=True, batch_size=config.batch_size)
    valid_dl = get_dataloader(is_train=False, batch_size=2 * config.batch_size)
    n_steps_per_epoch = math.ceil(len(train_dl.dataset) / config.batch_size)

    # 간단한 MLP 모델
    model = get_model(config.dropout)

    # 손실 함수 및 옵티마이저 생성
    loss_func = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=config.lr)

    # 학습
    example_ct = 0
    step_ct = 0
    for epoch in range(config.epochs):
        model.train()
        for step, (images, labels) in enumerate(train_dl):
            images, labels = images.to(device), labels.to(device)

            outputs = model(images)
            train_loss = loss_func(outputs, labels)
            optimizer.zero_grad()
            train_loss.backward()
            optimizer.step()

            example_ct += len(images)
            metrics = {
                "train/train_loss": train_loss,
                "train/epoch": (step + 1 + (n_steps_per_epoch * epoch))
                / n_steps_per_epoch,
                "train/example_ct": example_ct,
            }

            if step + 1 < n_steps_per_epoch:
                # wandb에 학습 메트릭 기록
                run.log(metrics)

            step_ct += 1

        val_loss, accuracy = validate_model(
            model, valid_dl, loss_func, log_images=(epoch == (config.epochs - 1))
        )

        # wandb에 학습 및 검증 메트릭 기록
        val_metrics = {"val/val_loss": val_loss, "val/val_accuracy": accuracy}
        run.log({**metrics, **val_metrics})

        # wandb에 모델 체크포인트 저장
        torch.save(model, "my_model.pt")
        run.log_model(
            "./my_model.pt",
            "my_mnist_model",
            aliases=[f"epoch-{epoch+1}_dropout-{round(run.config.dropout, 4)}"],
        )

        print(
            f"Epoch: {epoch+1}, Train Loss: {train_loss:.3f}, Valid Loss: {val_loss:3f}, Accuracy: {accuracy:.2f}"
        )

    # 테스트 세트가 있다면, 다음과 같이 Summary 메트릭으로 기록할 수 있습니다
    run.summary["test_accuracy"] = 0.8
이제 W&B를 사용해 첫 번째 모델 학습을 완료했습니다. 위의 링크 중 하나를 클릭해 메트릭을 확인하고, W&B 앱 UI의 Artifacts 탭에서 저장된 모델 체크포인트를 확인하세요

(선택 사항) W&B Alert 설정하기

Python 코드에서 Slack 또는 이메일로 알림을 보내기 위해 W&B Alerts를 생성합니다. 코드에서 트리거되는 Slack 또는 이메일 알림을 처음 설정할 때는 다음 두 단계를 수행해야 합니다:
  1. W&B User Settings에서 Alerts를 켭니다.
  2. 코드에 run.alert()를 추가합니다. 예를 들어:
run.alert(title="Low accuracy", text=f"Accuracy is below the acceptable threshold")
아래 셀에서는 run.alert() 사용 방법을 확인할 수 있는 간단한 예제를 보여줍니다.
import wandb

# wandb 실행 시작
with wandb.init(project="pytorch-intro") as run:

    # 모델 학습 루프 시뮬레이션
    acc_threshold = 0.3
    for training_step in range(1000):

        # 정확도를 위한 난수 생성
        accuracy = round(random.random() + random.random(), 3)
        print(f"Accuracy is: {accuracy}, {acc_threshold}")

        # wandb에 정확도 기록
        run.log({"Accuracy": accuracy})

        # 정확도가 임계값 이하이면 W&B Alert를 발생시키고 실행 중지
        if accuracy <= acc_threshold:
            # wandb Alert 전송
            run.alert(
                title="Low Accuracy",
                text=f"Accuracy {accuracy} at step {training_step} is below the acceptable threshold, {acc_threshold}",
            )
            print("Alert triggered")
            break
자세한 내용은 W&B Alerts 개요를 참조하세요.

다음 단계

다음 튜토리얼에서는 W&B Sweeps를 사용해 하이퍼파라미터를 최적화하는 방법을 학습합니다: PyTorch를 사용한 하이퍼파라미터 스윕