tensorboard 사용법 (SummaryWriter 사용법)

2024. 7. 21. 18:04DL

SummaryWriter.add_scalar는 TensorBoard에 수치형 데이터를 기록하는 데 사용되는 함수

add_scalar(tag, scalar_value, global_step=None, walltime=None)

매개변수 설명

  1. tag (str): 기록할 값의 이름. TensorBoard에서 그래프의 축 제목
  2. scalar_value (float): 기록할 수치형 값
  3. global_step (int, 선택 사항): 이 값을 통해 특정 시점(global step)을 지정할 수 있음. 일반적으로 epoch or batch index 사용. 이를 통해 그래프의 x축에 시점을 표시.
  4. walltime (float, 선택 사항): 기록 시점의 시간. 기본적으로는 현재 시간을 사용.

사용 예시

from torch.utils.tensorboard import SummaryWriter

# SummaryWriter를 초기화.
writer = SummaryWriter('runs/mnist_experiment_1')

for epoch in range(num_epochs):
    running_loss = 0.0
    for i, (inputs, labels) in enumerate(train_loader, 0):
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 100 == 99:  # 매 100 미니배치마다 로그남김.
            print(f'Epoch [{epoch + 1}/{num_epochs}], Step [{i + 1}/{len(train_loader)}], Loss: {running_loss / 100:.4f}')
            # writer.add_scalar를 사용하여 Loss 값 기입.
            writer.add_scalar('training loss', running_loss / 100, epoch * len(train_loader) + i)
            running_loss = 0.0

writer.close()

위 코드 설명

  1. tag: training loss는 TensorBoard에서 이 값이 어떤 것인지 설명하는 레이블.
  2. scalar_value: running_loss / 100은 기록할 실제 loss 값.
  3. global_step: epoch * len(train_loader) + i는 현재 epoch와 배치를 결합한 고유한 시점. 이를 통해 각 값이 언제 기록되었는지를 알 수 있음.

다른 사용 예제

add_scalar는 다양한 수치형 메트릭을 기록하는 데 사용할 수 있음 -> 정확도

# 훈련 정확도 기록
writer.add_scalar('training accuracy', accuracy, epoch)

# 검증 정확도 기록
writer.add_scalar('validation accuracy', val_accuracy, epoch)

이러한 기록을 통해 TensorBoard에서 훈련 및 검증 정확도의 변화를 쉽게 시각화 가능

학습 중간에 보기


import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 데이터셋 및 데이터 로더 준비
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)

# 간단한 모델 정의
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(28*28, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 10)

    def forward(self, x):
        x = x.view(-1, 28*28)
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

model = SimpleNN()

# 손실 함수 및 옵티마이저 정의
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# TensorBoard SummaryWriter 초기화
writer = SummaryWriter('runs/mnist_experiment_1')

# 훈련 루프
num_epochs = 5
for epoch in range(num_epochs):
    running_loss = 0.0
    for i, (inputs, labels) in enumerate(train_loader, 0):
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

        # 매 100 미니배치마다 로그를 남김
        if i % 100 == 99:
            print(f'Epoch [{epoch + 1}/{num_epochs}], Step [{i + 1}/{len(train_loader)}], Loss: {running_loss / 100:.4f}')
            writer.add_scalar('training loss', running_loss / 100, epoch * len(train_loader) + i)
            running_loss = 0.0

    # 에포크가 끝날 때마다 정확도 평가
    correct = 0
    total = 0
    with torch.no_grad():
        for inputs, labels in train_loader:
            outputs = model(inputs)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    accuracy = 100 * correct / total
    writer.add_scalar('training accuracy', accuracy, epoch)
    print(f'Epoch [{epoch + 1}/{num_epochs}], Accuracy: {accuracy:.2f}%')

# SummaryWriter를 닫음
writer.close()
print('Finished Training')

# TensorBoard 실행
# tensorboard --logdir=runs

추가적으로
태그 이름을 사용하여 그래프 그룹화: add_scalar를 호출할 때 사용하는 태그(tag) 이름을 적절하게 설정하여 그래프를 논리적으로 그룹화가 가능하다.
예를 들어, 태그 이름에 슬래시(/)를 포함하면 TensorBoard에서는 이를 계층 구조로 해석하여 그룹화할 수 있다.
아래 예시처럼 loss 따로 accuracy 따로 그룹화해서 볼 수 있다

writer.add_scalar('Loss/train', running_loss / 100, epoch * len(train_loader) + i)
writer.add_scalar('Accuracy/train', accuracy, epoch)