📊 다양한 시각화 방법

대표적으로 WandB는 학습log 시각화를 주로 사용한다.

대표적으로 다음과 같다.

  • Loss, Accuracy 그래프
  • Model parameter(gradient) 그래프
  • pred_img 시각화
  • sweep 그래프
  • Confusion Matrix
  • ROC, PR Curve

 

 

 

 

1.  Loss, Accuracy 그래프

💻 코드

wandb.log({'loss':loss}, step=epoch)
wandb.log({'val_loss': val_loss,
           'val_acc': val_accuracy })

 

📊 시각화


 

 

2.  Model parameter(gradient) 그래프

💻 코드

wandb.watch(model, criterion, log="all", log_freq=10)

log="all"을 주면 gradient와 parameter, bias를 모두 기록할 수 있다.

 

📊 시각화

 

 


3.  Pred_Img 시각화

💻 코드

ex_images.append(wandb.Image(data[0], 
                                  caption="Pred:{} Truth:{}".format(pred[0].item(), target[0])
                                  ))
  
 wandb.log({"Image": ex_images})

 

📊 시각화

cf) index바를 조절해 학습진행경과확인이 가능하다.

 


4.  sweep 그래프

💻 코드

sweep_id = wandb.sweep(sweep_config, project="mnist", entity='v2llain')
wandb.agent(sweep_id, run_sweeep, count=6)

 

📊 시각화

X축: configuration된 parameter이름

y축: 변경된 값

맨 우측: 성능측정값

 


5.  Confusion Matrix

💻 코드

sweep실행❌)

wandb.sklearn.plot_confusion_matrix(y_test, y_pred, 
                                    labels=classes_name)

 

sweep실행⭕️)

wandb.log({
      "Confusion Matrix":
      wandb.plot.confusion_matrix(preds=best_all_preds,
                                  y_true=best_all_labels,
                                  class_names=classes_name
                                  )})

 

📊 시각화

좌) sweep X.   우) sweep진행 시, 색별로 sweep구분가능.

 


6. ROC, PR Curve

💻 코드

wandb.log({'roc': wandb.plots.ROC(y_test, y_prob_pred, cnb.classes_)})
wandb.log({'pr': wandb.plots.precision_recall(y_test, y_prob_pred, cnb.classes_)})

 

📊 시각화

두 그래프 모두 상단에 위치할수록 좋은 그래프 (∵AUC가 클수록 좋기 때문.)

 

 

🧹 Sweep이란?

0. Overview

단 1%라도 성능을 올리기위해 많은 사람들이 부단한 노력을 한다. (ex. paperswithcode)

결국, 모델의 성능을 최대로 끌어올리기 위해서는 Hyper-parameter를 변경하며 최적의 값을 찾기위해 이에 대해서도 부단히 노력을 기울여야 하지만, 이는 매우 피곤하고 Cost를 많이 들게 만든다.

이를 위해 등장한 것이 바로 W&B의 Sweep이다!

 

 

 

1. Sweep이란?

기본적으로 Hyper-parameter를 자동으로 최적화주는 Tool

Hyper-parameter Seach방식으로 다음 3가지가 존재한다.

  • Grid 방식
  • Random 방식
  • Bayes 방식

선택한 search 방식으로 하이퍼 파라미터 튜닝이 완료 되면 WandB의 웹에서 제공되는 dashboard로 시각화된 모습을 볼 수 있다.

이렇게 시각화된 모습은 위의 그림과 같다. Sweep은 자동으로 tuning해주는 기능 뿐만 아니라,

각각의 hyper parameter들이 metric(accuracy, loss 등)에 얼마나 중요한 지 알려주고 상관관계를 보여주기에 필수적이라 할 수 있다.

(대시보드)

 

 

 

 

 

🧹 Sweep 사용법❗️

 

Tune Hyperparameters | Weights & Biases Documentation

Hyperparameter search and model optimization with W&B Sweeps

docs.wandb.ai

Sweep은 필히 2개의 단계(Initialize the Sweep, Run the Sweep Agent)가 필요하다.

 

 

1. Initialize the Sweep 

 ∙ Sweep Configuration를 정의

Sweep Initialize를 위해 먼저 구성요소(configuration)를 정의해야한다.

이를 위해 required와 option으로 나뉜다.

 program(어디에서) method(무엇을) parameters(어떻게)
최적화를 할 것인지 정의해야한다.

이때, 최적화 방법으로 3가지가 존재한다.
  • Grid 방식 : 가능한 모든 조합 탐색 (= Cost↑)
  • Random 방식 : random하게 선택 (= Cost↓, opt찾을확률↓)
  • Bayes 방식 : 이전에 시도한 hyper-parameter조합의 결과를 사용, 다음시도조합 추론시 사용 
    → 모델성능을 최대로 향상시킬 수 있는 hyper-parameter조합을 찾는다. (= 초기탐색이 느림)

 


이때, 특히나 parameters 파트가 중요하기에 좀 더 살펴보자.


values  value
Hyper-parameter에 대해 특정 값을 설정해서 우리가 원하는 값만 선택하게 해줌.
(value는 1가지 값을 설정해줄 때 사용)


distribution
values와 대조되는 방식.
특정 값을 설정하는 대신 원하는 분포 안에서 값을 선택.
Sweep에서는 uniform, normal, q_log_uniform과 같이 다양한 분포를 제공.
또한 선택된 분포를 min, max와 mu, sigma, q를 통해 자유롭게 변형가능.

min, max
분포의 최소∙최대값을 설정.

mu
  sigma

평균과 표준편차를 나타내는 값, 정규분포(normal)의 모양을 결정.

q

Quantization의 약자로 distribution에서 나온 값 X를 양자화.
ex) q를 2로 설정한다면 X는 2의 배수로 바뀜.
(ex. 식 round(X / q) *q를 적용하면, -2.96은 -2로 13.27은 14로 8.43은 8로 바뀜.)=

 ∙ project에 사용하기위해 Sweep API로 초기화

Sweep의 config가 제대로 정의가 됐다면 이제 프로젝트에 적용을 해줘야한다.

 

sweep 초기화 코드:

sweep_id = wandb.sweep(config.sweep_config)


위에서 정의된 config 변수를 입력으로 받고 sweep id를 출력해준다.

이 id는 다음 step에서 sweep을 실행시킬 때 고유한 identifier로 사용된다.

 

 

 

 

 

 

2. Run the Sweep Agent

  • 함수나 프로그램을 W&B서버에서 실행.

이제 본격적인 실행만이 남았다.

위에서 정의해준 configuration을 사용해 sweep을 진행하자.

 

sweep 진행코드:

wandb.agent(sweep_id, function=train, count=count)

이때, 위에서 출력된 sweep_id를 입력으로 넣어준다.

또한, function에 우리가 정의한 train함수를 넣어주고

sweep을 몇번 진행할 지 숫자를 count에 입력해준다.

성공적으로 Sweep 실행시 출력되는 화면.

 

 

 

 

 

cf). yaml 파일로 실행하는 방법.

project와 entity를 기입 가능한 곳

  • config 설정 하는 파일 (config.py 혹은 config.yaml)
  • wandb.sweep()
  • wandb.init()
  • wandb.agent()

config를 .py파일로 정의하는 방식과 .yaml파일로 정의하는 방식이 존재.yaml파일로 실행하는 방법에 대해 알아보자.


1. config.yaml 파일 생성

 

 

 

 

2. . yaml 파일, Sweep에 입력

wandb sweep config.yaml

 

 

3. Sweep id를 Agent에 입력

wandb agent SWEEP_ID

 

 

 

cf) wandb terminal에서 명령어로 지정하기.

∙ sweep 횟수 제한

wandb agent --count [LIMIT_NUM] [SWEEPID]

 

 

∙ Multi-GPU sweep 사용

CUDA_VISIBLE_DEVICES=0 wandb agent sweep_id
CUDA_VISIBLE_DEVICES=1 wandb agent sweep_id

 

 

 

 


 

 

 

🧹 W&B Sweep 실행을 위한 예시코드

from dataset import SweepDataset
from model import ConvNet
from optimize import build_optimizer
from utils import train_epoch

import wandb
import config

parser = argparse.ArgumentParser()
parser.add_argument('--batch-size', type=int, default=8, metavar='N')
parser.add_arguemnt('--epochs', type=int, default=10)                     
args = parser.parse_args()                   

wandb.config.update(args)

def train():
    wandb.init(config=config.hyperparameter_defaults)
    w_config = wandb.config

    loader = SweepDataset(w_config.batch_size, config.train_transform)
    model = ConvNet(w_config.fc_layer_size, w_config.dropout).to(config.DEVICE)
    optimizer = build_optimizer(model, w_config.optimizer, w_config.learning_rate)

    wandb.watch(model, log='all')

    for epoch in range(w_config.epochs):
        avg_loss = train_epoch(model, loader, optimizer, wandb)
        print(f"TRAIN: EPOCH {epoch + 1:04d} / {w_config.epochs:04d} | Epoch LOSS {avg_loss:.4f}")
        wandb.log({'Epoch': epoch, "loss": avg_loss, "epoch": epoch})     
        
sweep_id = wandb.sweep(config.sweep_config)
wandb.agent(sweep_id, train, count=2)

sweep을 위한 config 파일은 config.py에 구현되어 있습니다. 코드를 순서대로 설명하면 다음과 같습니다.

1. hyper parameter의 초기값을 wandb.init에 입력으로 넣어줍니다.
2. w_config는 sweep을 할 대상 hyper parameter입니다.
3. loader, model, optimizer 함수에 w_config를 매개변수로 전달해줍니다.
4. model을 정의하면 wandb.watch 함수로 gradient를 추적합니다.
5. epoch 별로 나오는 log를 wandb.log에 저장합니다.
6. config 파일에 정의해둔 구성 요소를 wandb.sweep에 입력합니다.
7. wandb.sweep에서 나온 id와 위에 구현된 train 함수, 그리고 횟수를 wandb.agent에 입력하고 sweep을 실행시킵니다.

 

참고) https://pebpung.github.io/wandb/2021/10/10/WandB-2.html

 

 

 


🧹 Sweep 시각화

WandB실행 이후, 시각화된 결과를 분석해보자. (대시보드)

이를 위해서는 Sweep workspace의 구성방식에 대해 알아봐야한다.

 

좌측 그래프: y축은 metric, X축은 생성된 날짜를 의미.

우측 표: hyper parameter가 metric(accuracy, loss 등)에 얼마나 중요한 지와 상관관계가 어느정도 인지도 알려줌.

 


 

위 그림은 hyper-parameter선택과정을 시각적으로 보여준 그림이다.

 ∙ X축: config에서 설정한 hyper-parameter의 종류

 ∙ y축: config에서 설정한 hyper-parameter의 범위

 

추가적으로 마우스를 가져다 놓으면 해당 그래프에서의 값을 알 수 있다.

📌 WandB가 왜 필요할까?

1. Model Experiment Pipeline

https://ml-ops.org/content/mlops-principles

위 그림을 보면 알 수 있듯, MLOps과정은 크게 3단계로 나뉜다.

 ∙ Project Design

 ∙ Experiment & Development

 ∙ 배포 및 운영

 

이중, 2단계인 "실험에 도움을 주는 Tool"중 하나가 바로 WandB이다.

(cf. TensorBoard도 존재.)

 

 

 

2. Configuration

ML구축을 위한 필수구성요소로 대표적인 예시는 다음과 같다.
∙ Dataset
∙ Metric
∙ Model
∙ Hyper-parameter

 

Training과정에서, 이 Configuration값을 적절하게 선택해줘야한다.

🧐 Batch size에 대하여
Data나 Model의 종류에 따라 적절한 Batch_size가 존재하기에
batch_size를 너무 작은값이나 큰값을 쓰면 오히려 학습이 잘 안되는 경향이 존재한다.

cf) 특정한 가설하에 연역적으로 증명가능할 때,
batch size를 2배 증가시키면 step size는 √2배 증가시켜야한다. 

cf) batch size를 증가시켰는데도 총 epoch수를 그대로 두면
한 epoch당 iteration수가 줄어들기에
그만큼 gradient로 parameter update를 덜 시키는 것이므로
Loss감소속도가 느려져 학습이 잘 안될 수도 있다.

그렇기에 적절한 Configuration설정은 준필수적이다.

 

특히, Dataset은 Data Augmentation

Metric은 추가하거나 교체하고, Model도 구조를 변경시키는 시간은 상대적으로 적은 시간이 들지만

 

Hyper-parameter Tuning의 경우 적절한 값을 찾기 위해서는 상당히 많은 시간을 할애해야한다.

Model의 parameter 최적화를 위해 Hyper-parameter를 적절히 조절해야하고, 이는 Hyper-parameter를 변경시키며 다양한 실험을 해야하기 때문이다.

 

이를 사람이 일일히 한다면?

즉, Hyper-parameter를 사람이 직접 일일히 tuning하는 작업은

매우 비효율적이고, 기록이 누락될수도 있고 이를 수기로 정리까지 해야하는, 

종합고민3종세트라 할 수 있겠다.

 

 

 

 

 

 

📌 WandB?

WandB(Weights & Biases)는 더 최적화된 모델을 빠른시간내에 만들 수 있게 도와주는, ML Experiment Tracking Tool이다.

주요기능

W&B Platform

  • Experiments: 머신러닝 모델 실험을 추적하기 위한 Dashboard 제공.
  • Artifacts: Dataset version 관리와 Model version 관리.
  • Tables: Data를 loging하여 W&B로 시각화하고 query하는 데 사용.
  • Sweeps: Hyper-parameter를 자동으로 tuning하여 최적화 함.
  • Reports: 실험을 document로 정리하여 collaborators와 공유.

 

 

 

📌 W&B Experiments. 함수 및 예제

모델학습 시, 모델 학습 log를 추적하여 Dashboard를 통해 시각화
이를 통해 학습이 잘 되고 있는지 빠르게 파악할 수 있다.

 

1. config setting

W&B실행을 위해 config파일이 필요하기에 

Hyper-parameter, Data명 등 학습에 필요한 구성들을 그룹화한다.

또한, 이 config파일은 sweep에 중요하게 사용된다.

config  = {
    'dataset': 'MNIST',
    'batch_size': 128,
    'epochs': 5,
    
    'architecture': 'CNN',
    'classes':10,
    'kernels': [16, 32],
    
    'weight_decay': 0.0005,
    'learning_rate': 1e-3,
    
    'seed': 42
}

 

 

 

 

 

 

2. Dataset with DataLoader

def make_loader(batch_size, train=True):
    full_dataset = datasets.MNIST(root='./data/MNIST', train=train, download=True,  transform=transforms.ToTensor())

    loader = DataLoader(dataset=full_dataset,
                        batch_size=batch_size,
                        shuffle=True, pin_memory=True, num_workers=2)
    return loader

 

 

 

 

 

3. CNN Model

class ConvNet(nn.Module):
    def __init__(self, kernels, classes=10):
        super(ConvNet, self).__init__()

        self.layer1 = nn.Sequential(
            nn.Conv2d(1, kernels[0], kernel_size=5, stride=1, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(16, kernels[1], kernel_size=5, stride=1, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2))
        self.fc = nn.Linear(7 * 7 * kernels[-1], classes)

    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = out.reshape(out.size(0), -1)
        out = self.fc(out)
        return out

추가적으로 W&B는 모델의 weights와 bias같은 parameter를 추적할 수 있다.

이를 통해 학습 도중 weights의 histogram이나 distribution을 통해 원활한 학습방향수정이 가능하다.

 

 

 

 

 

4. Train 함수

def train(model, loader, criterion, optimizer, config):
    wandb.watch(model, criterion, log="all", log_freq=10)

    example_ct = 0
    for epoch in tqdm(range(config.epochs)):
        cumu_loss = 0
        for images, labels in loader:

            images, labels = images.to(device), labels.to(device)

            outputs = model(images)
            loss = criterion(outputs, labels)
            cumu_loss += loss.item()

            optimizer.zero_grad()
            loss.backward()

            optimizer.step()

            example_ct +=  len(images)

        avg_loss = cumu_loss / len(loader)
        wandb.log({"loss": avg_loss}, step=epoch)
        print(f"TRAIN: EPOCH {epoch + 1:04d} / {config.epochs:04d} | Epoch LOSS {avg_loss:.4f}")

wandb.log()함수를 통해 loss함수를 시각화 할 수 있음.

이때, step을 epoch으로 받아 avg_loss값을 기록하는 것을 알 수 있다.

 

wandb.watch()는 Dashboard에서 실험 log를 시각화하는 역할을 수행.

 

 

5. Run 함수

def run(config=None):
    wandb.init(project='MNIST', entity='계정명', config=config)

    config = wandb.config

    train_loader = make_loader(batch_size=config.batch_size, train=True)
    test_loader = make_loader(batch_size=config.batch_size, train=False)

    model = ConvNet(config.kernels, config.classes).to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=config.learning_rate)

    train(model, train_loader, criterion, optimizer, config)
    test(model, test_loader)
    return model

wandb.int()으로 wandb web서버와 연결.

 

cf) project와 entity를 기입 가능한 곳

  • config 설정 하는 파일 (config.py 혹은 config.yaml)
  • wandb.sweep()
  • wandb.init()
  • wandb.agent()

 

 

 

 

6. 결과

실험결과, 각 에폭마다 해당 Layer에 전파되는 Gradient값들을 확인할 수 있다.

추가적으로 해당 epoch에 대한 gradient distribution의 경우 마우스를 가져다 놓으면 위의 그림처럼 확인가능하다.

+ Recent posts