Tensorboard와 WandB는 머신러닝과 딥러닝 모델 개발에 대한 모니터링 툴이다.
Tensorboard는 이름에서 알 수 있듯이 TensorFlow와 연계된 툴이지만 PyTorch에서도 사용할 수 있다.
여기서는 AlexNet을 이용해 CIFAR-10을 classification하는 예시를 통해 살펴보고자 한다.
Tensorboard 예시
from torch.utils.tensorboard import SummaryWriter # TensorBoard 사용 준비
writer = SummaryWriter("./runs/cv/alexnet")
writer를 이용하여 텐서보드에 기록할 준비를 한다.
tensorboard에는 add_scalar, add_scalars, add_graph, add_images, add_video 등 다양한 기록이 가능하다.
여기서는 간단하고 성능의 관찰에 필수적인 add_scalar와 add_scalars만을 기록했다.
from sklearn.metrics import accuracy_score, f1_score
def train_batches(loader, model, optimizer, loss_function, epoch):
# Set the model to train
model.train()
epoch_loss = 0.0
preds_list = []
labels_list = []
for images, labels in loader:
# Clear gradients
optimizer.zero_grad()
# Move to device
images = images.to(device)
labels = labels.to(device)
# Predict Labels
predictions = model(images)
loss = loss_function(predictions, labels)
# Backpropogation
loss.backward()
# Next Step
optimizer.step()
epoch_loss += loss.item()
# Extract indices having max probs and filter out the rest
preds_list.extend(predictions.argmax(dim=1).detach().cpu().numpy())
labels_list.extend(labels.detach().cpu().numpy())
train_acc = accuracy_score(labels_list, preds_list)
train_f1_macro = f1_score(labels_list, preds_list, average = 'macro')
train_f1_micro = f1_score(labels_list, preds_list, average = 'micro')
train_acc = round(train_acc, 4)
train_f1_macro = round(train_f1_macro, 4)
train_f1_micro = round(train_f1_micro, 4)
# 단일 scalar 작성
writer.add_scalar(tag = "Metric/Train_CE_loss", scalar_value = epoch_loss, global_step = epoch)
# 여러개의 scalars 한 번에 작성
writer.add_scalars(main_tag = "Metric/evaluations",
tag_scalar_dict = {"Train_Acc": train_acc,
"Train_F1_Macro": train_f1_macro,
"Train_F1_Micro": train_f1_micro,
},
global_step = epoch)
print("Epoch {0} - Train Data, CE loss: {1}, ACC: {2}, Macro F1: {3}".format(
epoch, epoch_loss, train_acc, train_f1_macro))
print("Micro F1: ", train_f1_micro)
def test_batches(loader, model, loss_function, epoch, process_name = 'Test'):
# Set the model to evaluate
model.eval()
epoch_loss = 0.0
preds_list = []
labels_list = []
for images, labels in loader:
# Move to device
images = images.to(device)
labels = labels.to(device)
# Predict Labels
predictions = model(images)
loss = loss_function(predictions, labels)
epoch_loss += loss.item()
# Extract indices having max probs and filter out the rest
preds_list.extend(predictions.argmax(dim=1).detach().cpu().numpy())
labels_list.extend(labels.detach().cpu().numpy())
acc = accuracy_score(labels_list, preds_list)
f1_macro = f1_score(labels_list, preds_list, average = 'macro')
f1_micro = f1_score(labels_list, preds_list, average = 'micro')
acc = round(acc, 4)
f1_macro = round(f1_macro, 4)
f1_micro = round(f1_micro, 4)
# 단일 scalar 작성
# process_name으로 validation인지 test인지 표시
writer.add_scalr(tag = f"Metric/{process_name}_CE_loss", scalar_value = epoch_loss, global_step = epoch)
# 여러개의 scalars 한 번에 작성
writer.add_scalars(main_tag = "Metric/evaluations",
tag_scalar_dict = {f"{process_name}_Acc": acc,
f"{process_name}_F1_Macro": f1_macro,
f"{process_name}_F1_Micro": f1_micro,
},
global_step = epoch)
print("Epoch {0} - {4} Data, CE loss: {1}, ACC: {2}, Macro F1: {3}".format(
epoch, epoch_loss, acc, f1_macro, process_name))
print("Micro F1: ", f1_micro)
return epoch_loss
# Declare Model
model = AlexNet(num_classes = 10)
# Define Loss function
cross_entropy = nn.CrossEntropyLoss()
# Define Optimizer
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01,
momentum = 0.9, weight_decay = 0.0005)
start = time.time()
for epoch in range(config.n_epochs):
epoch_start = time.time()
# Train Part
print('='*20,f" Epoch {epoch}: Train Step ",'='*20)
train_batches(train_loader, model, optimizer, cross_entropy)
end = time.time()
duration = end - epoch_start
print(f"Train Time: {duration: .4f}")
# Validation Part
print('='*20,f" Epoch {epoch}: Validation Step ",'='*20)
val_start = time.time()
test_batches(val_loader, model, cross_entropy, process_name = 'Validation')
end = time.time()
duration = end - val_start
print(f"Validation Time: {duration: .4f}")
duration = end - epoch_start
print(f"Taken Time for Epoch {epoch} is {duration: .4f}")
tensorboard를 runs가 저장되어 있는 폴더에서 연 다음 VS Code로 열거나,
command에서 tensorboard --logdir=./runs와 같이 저장된 경로를 지정하는 명령어를 통해 열면 위와 같은 창이 뜬다.
맨 처음에는 Time Series가 뜨는데 시간의 흐름에 따른 loss가 evaluation metrics 등의 내용이 보인다.
add_scalar로 개별적으로 입력한 Train_CE_loss와 Valdation_CE_loss가 보이며,
add_scalars로 입력한 항목들은 모두 하나의 그래프 안에서 overlapping되어 보이게 된다.
여러 지표를 개별적으로 볼것인지 겹치도록 그릴것인지는 본인이 결정하면 된다.
맨 위쪽의 scalars 항목에서도 loss와 evaluation metrics를 자세하게 확인할 수 있다.
WandB 예시
WandB는 Weights & Biases의 약자로 스스로를 MLOps 툴이라고 소개하고 있다.
# 온라인 기반이기 때문에 로그인을 해준다.
wandb.login()
repo = 내가 가진 id의 아래에 project를 생성하고 그 아래에 다양한 모델이나,
하나의 모델에 대한 다양한 실험을 기록하여 살펴볼 수 있다.
여기서는 computer-vision-models란 프로젝트 아래에 AlexNet_v0라는 이름의 실험을 하나 설정한다.
wandb_run = wandb.init(
project = "computer-vision-models",
name = "AlexNet_v0" #displayed run name
config = {
"learning_rate": lr,
"epochs": config.n_epochs
}
)
WandB에 loss나 performance metrics를 기록하는 방법은 아래와 같다.
from sklearn.metrics import accuracy_score, f1_score
def train_batches(loader, model, optimizer, loss_function, epoch):
# Set the model to train
model.train()
epoch_loss = 0.0
preds_list = []
labels_list = []
for images, labels in loader:
# Clear gradients
optimizer.zero_grad()
# Move to device
images = images.to(device)
labels = labels.to(device)
# Predict Labels
predictions = model(images)
loss = loss_function(predictions, labels)
# Backpropogation
loss.backward()
# Next Step
optimizer.step()
epoch_loss += loss.item()
# Extract indices having max probs and filter out the rest
preds_list.extend(predictions.argmax(dim=1).detach().cpu().numpy())
labels_list.extend(labels.detach().cpu().numpy())
train_acc = accuracy_score(labels_list, preds_list)
train_f1_macro = f1_score(labels_list, preds_list, average = 'macro')
train_f1_micro = f1_score(labels_list, preds_list, average = 'micro')
train_acc = round(train_acc, 4)
train_f1_macro = round(train_f1_macro, 4)
train_f1_micro = round(train_f1_micro, 4)
# 여러개의 지표들 한 번에 작성
wandb.log({"epoch": epoch,
"Train_Loss": epoch_loss,
"Train_Acc": train_acc,
"Train_F1_Macro": train_f1_macro,
"Train_F1_Micro": train_f1_micro,})
print("Epoch {0} - Train Data, CE loss: {1}, ACC: {2}, Macro F1: {3}".format(
epoch, epoch_loss, train_acc, train_f1_macro))
print("Micro F1: ", train_f1_micro)
def test_batches(loader, model, loss_function, epoch, process_name = 'Test'):
# Set the model to evaluate
model.eval()
epoch_loss = 0.0
preds_list = []
labels_list = []
for images, labels in loader:
# Move to device
images = images.to(device)
labels = labels.to(device)
# Predict Labels
predictions = model(images)
loss = loss_function(predictions, labels)
epoch_loss += loss.item()
# Extract indices having max probs and filter out the rest
preds_list.extend(predictions.argmax(dim=1).detach().cpu().numpy())
labels_list.extend(labels.detach().cpu().numpy())
acc = accuracy_score(labels_list, preds_list)
f1_macro = f1_score(labels_list, preds_list, average = 'macro')
f1_micro = f1_score(labels_list, preds_list, average = 'micro')
acc = round(acc, 4)
f1_macro = round(f1_macro, 4)
f1_micro = round(f1_micro, 4)
# 여러개의 지표들 한 번에 작성
# process_name으로 validation인지 test인지 표시
wandb.log({"epoch": epoch,
f"{process_name}_Loss": epoch_loss,
f"{process_name}_Acc": acc,
f"{process_name}_F1_Macro": f1_macro,
f"{process_name}_F1_Micro": f1_micro,})
print("Epoch {0} - {4} Data, CE loss: {1}, ACC: {2}, Macro F1: {3}".format(
epoch, epoch_loss, acc, f1_macro, process_name))
print("Micro F1: ", f1_micro)
return epoch_loss
# wandb의 현재 run을 완료한 다음 서버로 데이터를 업로드한다.
wandb.finish()
위의 코드를 활용하여 AlexNet을 학습하면 다음과 같다.
특히 모델을 학습하거나 중단한 다음 wandb.finish()로 종료하는 것이 중요하다.
그렇지 않고 다시 login을 하거나 init를 하면 에러를 만나게 된다.
wandb 상에서 2개의 모델을 비교하기 위해서 임시로 2개의 AlexNet을 학습시켰다.
Figure 4에서는 computer-vision-models라는 project 아래에 있는 여러 모델의 모니터링 현황을 확인할 수 있다.
왼쪽 상단을 보면 runs 항목에 두 개의 모델이 나타남을 확인할 수 있다.
Figure 5를 보면 크게 Charts와 System으로 나뉘는 것을 알 수 있다.
Figure 5의 상황은 하나의 모델에 대한 하이퍼파라미터 튜닝이나 데이터의 변화 등을 추적하는 상황이라고 가정할 수 있다. Loss나 metrics가 동일하기 때문에 overlapping된 지표들을 통해서 두 개의 모델을 쉽게 비교할 수 있다.
Figure 6~8의 System 내용을 확인하면 GPU의 memory와 power usage, temperature 등 뿐만 아니라
시스템 메모리, CPU 활용 등등 하드웨어의 상황에 대해 모니터링할 수 있다.
하드웨어 최적화나 리소스 관리 등의 측면에서 중요한 항목으로 보인다.
Wandb는 써본지 얼마되지 않았는데, 온라인 기반이라 모니터링하기 편했다.
Invite Teammates 항목이 있는걸 보면 집단으로 함께 일할 때 현 상황을 공유하기도 좋아 보인다.
또한 하드웨어 모니터링도 가능해서 유용해보인다.
위의 장점 때문에 앞으로 tensorboard보다는 wandb로 모니터링을 진행할듯하다.
References:
[업스테이지] AI 심화 학습 - 딥러닝 강의 in 패스트캠퍼스&업스테이지 AI Lab 1기
https://tutorials.pytorch.kr/intermediate/tensorboard_tutorial.html
https://pytorch.org/docs/stable/tensorboard.html
https://docs.wandb.ai/quickstart
https://docs.wandb.ai/tutorials/pytorch
'Deep Learning' 카테고리의 다른 글
Meta, Few-shot, Zero-shot, Active Learning (0) | 2024.10.25 |
---|---|
딥러닝 모델 분석과 구현 정리 (0) | 2024.04.24 |
PyTorch Image Datasets, Custom Dataset, Fix Seed (0) | 2024.03.27 |
알아두면 좋은 주요 딥러닝 모델들 (0) | 2024.02.22 |
Memory Requirement of Deep Learning Models (0) | 2024.02.01 |