3.5. Bộ dữ liệu Phân loại Ảnh (Fashion-MNIST)¶
Ở Section 18.9, chúng ta đã huấn luyện bộ phân loại Naive Bayes, sử dụng bộ dữ liệu MNIST được giới thiệu vào năm 1998 [LeCun et al., 1998]. Mặc dù MNIST từng là một bộ dữ liệu tốt để đánh giá xếp hạng (benchmark), các mô hình đơn giản theo tiêu chuẩn ngày nay cũng có thể đạt được độ chính xác phân loại lên tới 95%. Điều này khiến nó không phù hợp cho việc phân biệt độ mạnh yếu của các mô hình. Ngày nay, MNIST được dùng trong các phép kiểm tra sơ bộ hơn là dùng để đánh giá xếp hạng. Để cải thiện vấn đề này, chúng ta sẽ tập trung thảo luận trong các mục tiếp theo về một bộ dữ liệu tương tự nhưng phức tạp hơn, đó là bộ dữ liệu Fashion-MNIST [Xiao et al., 2017] được giới thiệu vào năm 2017.
%matplotlib inline
from d2l import mxnet as d2l
from mxnet import gluon
import sys
d2l.use_svg_display()
3.5.1. Tải về Bộ dữ liệu¶
Cũng giống như với MNIST, Gluon giúp việc tải và nạp bộ dữ liệu
FashionMNIST vào bộ nhớ trở nên dễ dàng với lớp FashionMNIST
trong
gluon.data.vision
. Các cơ chế của việc nạp và khám phá bộ dữ liệu sẽ
được hướng dẫn ngắn gọn bên dưới. Vui lòng tham khảo
Section 18.9 để biết thêm chi tiết về việc nạp dữ liệu.
mnist_train = gluon.data.vision.FashionMNIST(train=True)
mnist_test = gluon.data.vision.FashionMNIST(train=False)
FashionMNIST chứa các hình ảnh thuộc 10 lớp, mỗi lớp có 6000 ảnh trong tập huấn luyện và 1000 ảnh trong tập kiểm tra. Do đó, tập huấn luyện và tập kiểm tra sẽ chứa tổng cộng lần lượt 60000 và 10000 ảnh.
len(mnist_train), len(mnist_test)
(60000, 10000)
Các ảnh trong Fashion-MNIST tương ứng với các lớp: áo phông, quần dài, áo thun, váy, áo khoác, dép, áo sơ-mi, giày thể thao, túi và giày cao gót. Hàm dưới đây giúp chuyển đổi các nhãn giá trị số thành tên của từng lớp.
# Saved in the d2l package for later use
def get_fashion_mnist_labels(labels):
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[int(i)] for i in labels]
Chúng ta có thể tạo một hàm để minh hoạ các mẫu này.
# Saved in the d2l package for later use
def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):
"""Plot a list of images."""
figsize = (num_cols * scale, num_rows * scale)
_, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
axes = axes.flatten()
for i, (ax, img) in enumerate(zip(axes, imgs)):
ax.imshow(img.asnumpy())
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
if titles:
ax.set_title(titles[i])
return axes
Dưới đây là các hình ảnh và nhãn tương ứng của chúng (ở dạng chữ) từ một vài mẫu đầu tiên trong tập huấn luyện.
X, y = mnist_train[:18]
show_images(X.squeeze(axis=-1), 2, 9, titles=get_fashion_mnist_labels(y));
3.5.2. Đọc một Minibatch¶
Để đọc dữ liệu từ tập huấn luyện và tập kiểm tra một cách dễ dàng hơn,
chúng ta sử dụng một DataLoader
có sẵn thay vì tạo từ đầu như đã làm
ở Section 3.2. Nhắc lại là ở mỗi vòng lặp, một
DataLoader
sẽ đọc một minibatch của tập dữ liệu với kích thước
batch_size
.
Trong quá trình huấn luyện, việc đọc dữ liệu có thể gây ra hiện tượng
nghẽn cổ chai hiệu năng đáng kể, trừ khi mô hình đơn giản hoặc máy tính
rất nhanh. Một tính năng tiện dụng của DataLoader
là khả năng sử
dụng đa tiến trình (multiple processes) để tăng tốc việc đọc dữ liệu.
Ví dụ, chúng ta có thể dùng 4 tiến trình để đọc dữ liệu (thông qua
num_workers
). Vì tính năng này hiện tại không được hỗ trợ trên
Windows, đoạn mã lập trình dưới đây sẽ kiểm tra nền tảng hệ điều hành để
đảm bảo rằng chúng ta không làm phiền những người dùng Windows với các
thông báo lỗi sau này.
# Saved in the d2l package for later use
def get_dataloader_workers(num_workers=4):
# 0 means no additional process is used to speed up the reading of data.
if sys.platform.startswith('win'):
return 0
else:
return num_workers
Dưới đây, chúng ta chuyển đổi dữ liệu hình ảnh từ uint8 sang số thực dấu
phẩy động (floating point number) 32 bit với lớp ToTensor
. Ngoài
ra, bộ chuyển đổi sẽ chia tất cả các số cho 255 để các điểm ảnh có giá
trị từ 0 đến 1. Lớp ToTensor
cũng chuyển kênh hình ảnh từ chiều cuối
cùng sang chiều thứ nhất để tạo điều kiện cho các tính toán của mạng
nơ-ron tích chập được giới thiệu sau này. Thông qua hàm
transform_first
của tập dữ liệu, chúng ta có thể áp dụng phép biến
đổi ToTensor
cho phần tử đầu tiên của mỗi ví dụ (một ví dụ chứa hai
phần tử là ảnh và nhãn).
batch_size = 256
transformer = gluon.data.vision.transforms.ToTensor()
train_iter = gluon.data.DataLoader(mnist_train.transform_first(transformer),
batch_size, shuffle=True,
num_workers=get_dataloader_workers())
Hãy cùng xem thời gian cần thiết để hoàn tất việc đọc dữ liệu huấn luyện.
timer = d2l.Timer()
for X, y in train_iter:
continue
'%.2f sec' % timer.stop()
'5.45 sec'
3.5.3. Kết hợp Tất cả lại với nhau¶
Bây giờ, chúng ta sẽ định nghĩa hàm load_data_fashion_mnist
để nạp
và đọc bộ dữ liệu Fashion-MNIST. Hàm này sẽ trả về các iterator cho dữ
liệu của cả tập huấn luyện và tập kiểm định. Thêm nữa, nó chấp nhận một
tham số tùy chọn để thay đổi kích thước hình ảnh đầu vào.
# Saved in the d2l package for later use
def load_data_fashion_mnist(batch_size, resize=None):
"""Download the Fashion-MNIST dataset and then load into memory."""
dataset = gluon.data.vision
trans = [dataset.transforms.Resize(resize)] if resize else []
trans.append(dataset.transforms.ToTensor())
trans = dataset.transforms.Compose(trans)
mnist_train = dataset.FashionMNIST(train=True).transform_first(trans)
mnist_test = dataset.FashionMNIST(train=False).transform_first(trans)
return (gluon.data.DataLoader(mnist_train, batch_size, shuffle=True,
num_workers=get_dataloader_workers()),
gluon.data.DataLoader(mnist_test, batch_size, shuffle=False,
num_workers=get_dataloader_workers()))
Dưới đây, chúng ta xác nhận rằng kích thước hình ảnh đã được thay đổi.
train_iter, test_iter = load_data_fashion_mnist(32, (64, 64))
for X, y in train_iter:
print(X.shape)
break
(32, 1, 64, 64)
Giờ chúng ta đã sẵn sàng để làm việc với bộ dữ liệu FashionMNIST trong các mục tiếp theo.
3.5.4. Tóm tắt¶
- Fashion-MNIST là một tập dữ liệu phân loại trang phục bao gồm các hình ảnh đại diện cho 10 lớp.
- Chúng ta sẽ sử dụng tập dữ liệu này trong các mục và chương tiếp theo để đánh giá các thuật toán phân loại khác nhau.
- Chúng ta lưu trữ kích thước của mỗi hình ảnh với chiều cao \(h\)
chiều rộng \(w\) điểm ảnh dưới dạng \(h \times w\) hoặc
(h, w)
. - Iterator cho dữ liệu là nhân tố chính để đạt được hiệu suất cao. Hãy sử dụng các iterator được lập trình tốt để tận dụng khả năng chạy đa tiến trình, tránh làm chậm vòng lặp huấn luyện.
3.5.5. Bài tập¶
- Việc giảm
batch_size
(ví dụ xuống 1) có ảnh hưởng tới tốc độ đọc dữ liệu hay không? - Với người dùng không sử dụng Windows, hãy thử thay đổi
num_workers
để xem nó ảnh hưởng đến hiệu năng đọc dữ liệu như thế nào. Vẽ đồ thị hiệu năng tương ứng với số tiến trình được sử dụng. - Sử dụng tài liệu MXNet để xem các bộ dữ liệu có sẵn khác trong
mxnet.gluon.data.vision
. - Sử dụng tài liệu MXNet để xem những phép biến đổi nào có sẵn trong
mxnet.gluon.data.vision.transforms
.
3.5.6. Thảo luận¶
3.5.7. Những người thực hiện¶
Bản dịch trong trang này được thực hiện bởi:
- Đoàn Võ Duy Thanh
- Nguyễn Lê Quang Nhật
- Vũ Hữu Tiệp
- Lê Khắc Hồng Phúc
- Phạm Hồng Vinh
- Phạm Minh Đức