Chúng ta sẽ tìm hiểu cách sử dụng PyTorch kết hợp với TensorBoard để trực quan hóa kết quả hoạt động của mạng nơ-ron. Trong bài hướng dẫn này, chúng ta sẽ làm việc với bộ dữ liệu Fashion-MNIST và thực hiện các bước sau:
- Đọc dữ liệu và áp dụng các phép biến đổi phù hợp.
- Thiết lập TensorBoard.
- Ghi thông tin vào TensorBoard.
- Kiểm tra cấu trúc mô hình bằng TensorBoard.
- Tạo phiên bản tương tác của quá trình huấn luyện với ít mã nguồn hơn.
Đầu tiên, chúng ta cần thiết lập môi trường và đọc dữ liệu:
# Nhập thư viện cần thiết
import matplotlib.pyplot as plt
import numpy as np
import torch
import torchvision
from torchvision import datasets, transforms
from torch import nn, optim
# Biến đổi dữ liệu
data_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
# Đọc tập dữ liệu
train_data = datasets.FashionMNIST('./data', download=True, train=True, transform=data_transform)
test_data = datasets.FashionMNIST('./data', download=True, train=False, transform=data_transform)
# Tải dữ liệu
train_loader = torch.utils.data.DataLoader(train_data, batch_size=4, shuffle=True, num_workers=2)
test_loader = torch.utils.data.DataLoader(test_data, batch_size=4, shuffle=False, num_workers=2)
# Các lớp trong bộ dữ liệu
categories = ['Áo thun', 'Quần', 'Áo len', 'Váy', 'Áo khoác', 'Dép', 'Áo sơ mi', 'Giày thể thao', 'Túi xách', 'Giày bốt cổ ngắn']
# Hàm hiển thị ảnh đơn lẻ
def show_image(img, single_channel=False):
if single_channel:
img = img.mean(dim=0)
img = img / 2 + 0.5
np_img = img.numpy()
if single_channel:
plt.imshow(np_img, cmap='Greys')
else:
plt.imshow(np.transpose(np_img, (1, 2, 0)))
Tiếp theo, chúng ta định nghĩa kiến trúc của mô hình:
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv_layer_1 = nn.Conv2d(1, 6, 5)
self.pool_layer = nn.MaxPool2d(2, 2)
self.conv_layer_2 = nn.Conv2d(6, 16, 5)
self.fc_layer_1 = nn.Linear(16 * 4 * 4, 120)
self.fc_layer_2 = nn.Linear(120, 84)
self.fc_layer_3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool_layer(torch.relu(self.conv_layer_1(x)))
x = self.pool_layer(torch.relu(self.conv_layer_2(x)))
x = x.view(-1, 16 * 4 * 4)
x = torch.relu(self.fc_layer_1(x))
x = torch.relu(self.fc_layer_2(x))
x = self.fc_layer_3(x)
return x
model = Model()
Sau đó, chúng ta xác định hàm mất mát và tối ưu hóa:
loss_function = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
Thiết lập TensorBoard:
from torch.utils.tensorboard import SummaryWriter
# Khởi tạo ghi chép cho TensorBoard
logger = SummaryWriter('runs/fashion_mnist_experiment')
Ghi một lưới ảnh vào TensorBoard:
# Lấy một số mẫu ngẫu nhiên từ dữ liệu huấn luyện
data_iterator = iter(train_loader)
samples, labels = data_iterator.next()
# Tạo lưới ảnh
image_grid = torchvision.utils.make_grid(samples)
# Hiển thị ảnh
show_image(image_grid, single_channel=True)
# Ghi ảnh vào TensorBoard
logger.add_image('Four Fashion-MNIST Images', image_grid)
Kiểm tra cấu trúc mô hình:
logger.add_graph(model, samples)
logger.close()
Thêm tính năng chiếu dữ liệu:
# Chọn ngẫu nhiên các điểm dữ liệu và nhãn
def select_random(data, targets, count=100):
assert len(data) == len(targets)
permutation = torch.randperm(len(data))
return data[permutation][:count], targets[permutation][:count]
# Lấy các ảnh và nhãn ngẫu nhiên
random_images, random_labels = select_random(train_data.data, train_data.targets)
# Lấy tên các lớp tương ứng
category_names = [categories[label] for label in random_labels]
# Chuẩn bị dữ liệu đầu vào
features = random_images.view(-1, 28 * 28)
# Thêm dữ liệu chiếu vào TensorBoard
logger.add_embedding(features, metadata=category_names, label_img=random_images.unsqueeze(1))
logger.close()
Theo dõi quá trình huấn luyện:
# Hàm hỗ trợ
def probabilities_to_predictions(network, images):
outputs = network(images)
_, predictions = torch.max(outputs, 1)
probs = [torch.softmax(el, dim=0)[i].item() for i, el in zip(predictions, outputs)]
return predictions.numpy().squeeze(), probs
def visualize_predictions(network, images, labels):
preds, probs = probabilities_to_predictions(network, images)
figure = plt.figure(figsize=(12, 48))
for index in range(4):
subplot = figure.add_subplot(1, 4, index + 1, xticks=[], yticks=[])
show_image(images[index], single_channel=True)
subplot.set_title("{0}, {1:.1f}%\n(label: {2})".format(
categories[preds[index]],
probs[index] * 100,
categories[labels[index]]),
color=('green' if preds[index] == labels[index] else 'red'))
return figure
total_loss = 0.0
for epoch in range(1):
for step, (inputs, labels) in enumerate(train_loader, 0):
optimizer.zero_grad()
outputs = model(inputs)
loss = loss_function(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
if step % 1000 == 999:
logger.add_scalar('Training Loss', total_loss / 1000, epoch * len(train_loader) + step)
logger.add_figure('Predictions vs Actuals', visualize_predictions(model, inputs, labels), global_step=epoch * len(train_loader) + step)
total_loss = 0.0
print('Huấn luyện hoàn tất')
Cuối cùng, đánh giá hiệu suất mô hình:
# Dự đoán xác suất và nhãn
predictions_probabilities = []
predicted_labels = []
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = model(images)
predictions_probabilities.extend([torch.softmax(el, dim=0) for el in outputs])
predicted_labels.append(labels)
test_probs = torch.cat([torch.stack(batch) for batch in predictions_probabilities])
test_labels = torch.cat(predicted_labels)
# Vẽ đường cong Precision-Recall
def plot_pr_curve(class_index, test_probs, test_labels, global_step=0):
truth_values = test_labels == class_index
probabilities = test_probs[:, class_index]
logger.add_pr_curve(categories[class_index], truth_values, probabilities, global_step=global_step)
logger.close()
for idx in range(len(categories)):
plot_pr_curve(idx, test_probs, test_labels)