티스토리 뷰

 

 

이번엔 Pytorch를 사용하면서 데이터, 학습 과정 등의 시각화에 유용한 TensorBoard를 사용하는 방법을 한번 알아보도록 하겠습니다.


 

1. Install

우선 TensorBoard는 이름 그대로 Tensorflow를 위해서 개발된 Tools입니다. 그래서 Tensorflow에서만 거의 사용이 되었지만 정말 감사하게도 Pytorch에서도 TensorBoard를 사용할 수 있도록 TensorBoardX라는 라이브러리를 개발을 해주셔서 이제는 Pytorch에서도 Tensorboard를 사용할 수 있게 되었습니다.

 

TensorboardX를 사용하려면 pip을 사용해 TensorboardX를 설치해야 합니다.

pip install tensorboardX

 

2. Sin, Cos Function을 그려보기.

사실 이건 굳이 Pytorch가 아니더라도 사용할 수 있는 기능입니다. 그치만 Pytorch 코드를 이용해서 하기 전에 간단하게 우리가 수학시간때 배운 Sin, Cos 함수를 TensorBoard에 띄어보도록 하겠습니다.

 

# sin과 cos 함수를 그려주기 위해 math 함수를 선언
import math
# tensorboard에 data를 올릴려면 SummaryWriter를 선언 해줘야 합니다.
from tensorboardX import SummaryWriter

writer = SummaryWriter(logdir='scalar/sin&cos')

for step in range(-360, 360):
    angle_rad = step * math.pi / 180
    writer.add_scalar('sin', math.sin(angle_rad), step)
    writer.add_scalar('cos', math.cos(angle_rad), step)
    
writer.close()

 

보통 딥러닝 공부하시는 분들은 Google Colab을 많이 사용하시는데 Colab에서 하는 방법이랑 파이참이든 VScode든 이런곳에다 Code를 작성하고 Terminal 창에서 python test.py 이런식으로 하시는 분들을 위해서 각각 설명을 드리도록 하겠습니다.

# 1. Google Colab
%load_ext tensorboard
%tensorboard --logdir scalar --port=6006

# 2. Pycharm, VSCode etc..
> tensorboard --logdir runs

 

 

3. 그래프를 동일한 좌표에 그려보기

위에서는 각각 파형을 다른 좌표평면에다가 그려보았다면 여기서는 동일한 좌표평면에다가 다른 색으로 구분지어서 그려보도록 하겠습니다.

 

# sin과 cos 함수를 그려주기 위해 math 함수를 선언
import math
# tensorboard에 data를 올릴려면 SummaryWriter를 선언 해줘야 합니다.
from tensorboardX import SummaryWriter

writer = SummaryWriter(logdir='scalar/sin&cos')

for step in range(-360, 360):
    angle_rad = step * math.pi / 180
    writer.add_scalars('sin and cos', {'sin': math.sin(angle_rad), 'cos': math.cos(angle_rad)}, step)
    
writer.close()

# Load the TensorBoard notebook extension
%load_ext tensorboard

%tensorboard --logdir scalar --port=6006

 

 

4. Loss를 실시간으로 tensorboard에 그리기

이번에는 Pytorch 공식 한국 홈페이지에 나온 FashionMNIST 데이터셋을 이용한 코드를 응용해서 예시를 보여드리도록 하겠습니다.

 

4-1. 필요한 라이브러리 선언

import math
from tensorboardX import SummaryWriter
import matplotlib.pyplot as plt
import numpy as np

import torch
import torchvision
import torchvision.transforms as transforms

import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

4-2. Tensorboard에 작성될 이름(?) 지정

# 기본 `log_dir` 은 "runs"이며, 여기서는 더 구체적으로 지정하였습니다
writer = SummaryWriter('runs/fashion_mnist_experiment_1')

4-3. Data Loader(Fashion-MNIST)

# transforms
transform = transforms.Compose(
    [transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))])

# datasets
trainset = torchvision.datasets.FashionMNIST('./data',
    download=True,
    train=True,
    transform=transform)
testset = torchvision.datasets.FashionMNIST('./data',
    download=True,
    train=False,
    transform=transform)

# dataloaders
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                        shuffle=True, num_workers=2)


testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                        shuffle=False, num_workers=2)

# 분류 결과를 위한 상수
classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
        'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot')

# 이미지를 보여주기 위한 헬퍼(helper) 함수
# (아래 `plot_classes_preds` 함수에서 사용)
def matplotlib_imshow(img, one_channel=False):
    if one_channel:
        img = img.mean(dim=0)
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    if one_channel:
        plt.imshow(npimg, cmap="Greys")
    else:
        plt.imshow(np.transpose(npimg, (1, 2, 0)))

4-4. Network 및 Optimizer, loss function 선언

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 4 * 4, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 4 * 4)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

4-5. Custom Function

def images_to_probs(net, images):
    '''
    학습된 신경망과 이미지 목록으로부터 예측 결과 및 확률을 생성합니다
    '''
    output = net(images)
    # convert output probabilities to predicted class
    _, preds_tensor = torch.max(output, 1)
    preds = np.squeeze(preds_tensor.numpy())
    return preds, [F.softmax(el, dim=0)[i].item() for i, el in zip(preds, output)]


def plot_classes_preds(net, images, labels):
    '''
    학습된 신경망과 배치로부터 가져온 이미지 / 라벨을 사용하여 matplotlib
    Figure를 생성합니다. 이는 신경망의 예측 결과 / 확률과 함께 정답을 보여주며,
    예측 결과가 맞았는지 여부에 따라 색을 다르게 표시합니다. "images_to_probs"
    함수를 사용합니다.
    '''
    preds, probs = images_to_probs(net, images)
    # 배치에서 이미지를 가져와 예측 결과 / 정답과 함께 표시(plot)합니다
    fig = plt.figure(figsize=(12, 48))
    for idx in np.arange(4):
        ax = fig.add_subplot(1, 4, idx+1, xticks=[], yticks=[])
        matplotlib_imshow(images[idx], one_channel=True)
        ax.set_title("{0}, {1:.1f}%\n(label: {2})".format(
            classes[preds[idx]],
            probs[idx] * 100.0,
            classes[labels[idx]]),
                    color=("green" if preds[idx]==labels[idx].item() else "red"))
    return fig

4-6. Training & watching Tensorboard

running_loss = 0.0
# Load the TensorBoard notebook extension
%load_ext tensorboard

%tensorboard --logdir runs --port=6006
for epoch in range(1):  # 데이터셋을 여러번 반복

    for i, data in enumerate(trainloader, 0):

        # [inputs, labels]의 목록인 data로부터 입력을 받은 후;
        inputs, labels = data

        # 변화도(Gradient) 매개변수를 0으로 만들고
        optimizer.zero_grad()

        # 순전파 + 역전파 + 최적화를 한 후
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 1000 == 999:    # 매 1000 미니배치마다...

            # ...학습 중 손실(running loss)을 기록하고
            writer.add_scalar('training loss',
                            running_loss / 1000,
                            epoch * len(trainloader) + i)

            # ...무작위 미니배치(mini-batch)에 대한 모델의 예측 결과를 보여주도록
            # Matplotlib Figure를 기록합니다
            writer.add_figure('predictions vs. actuals',
                            plot_classes_preds(net, inputs, labels),
                            global_step=epoch * len(trainloader) + i)
            running_loss = 0.0
print('Finished Training')

 

5. 요약

Tensorboard를 사용하려면 우선

writer = SummaryWriter(logdir='scalar/sin&cos')

이런식으로 Tensorboard에 이름(?)을 작성해 주시고

 

writer.add_scalar()

writer.close()

이런식을오 Tensorboard에 그릴 내용들을 작성한 후 writer.close()를 작성해줍니다.

그리고 실시간으로 Tensorboard로 확인하기 위해서 

# Load the TensorBoard notebook extension
%load_ext tensorboard

%tensorboard --logdir scalar --port=6006

해당 내용을 작성을 해주시면 됩니다.

 

 

Reference

- https://tutorials.pytorch.kr/intermediate/tensorboard_tutorial.html

- https://github.com/lanpa/tensorboardX

Comments