.. raw:: html
.. raw:: html
.. raw:: html
.. _sec_vgg:
Mạng sử dụng Khối (VGG)
=======================
.. raw:: html
Mặc dù AlexNet đã chứng minh rằng các mạng nơ-ron tích chập có thể đạt
được kết quả tốt, nó lại không cung cấp một khuôn mẫu chung để định
hướng nghiên cứu sau này trong việc thiết kế các mạng mới. Trong các
phần tiếp theo, chúng tôi sẽ giới thiệu một số khái niệm dựa trên thực
nghiệm được sử dụng rộng rãi khi thiết kế mạng học sâu.
.. raw:: html
| Sự phát triển trong lĩnh vực này có nét tương đồng tiến triển trong
ngành thiết kế vi xử lý, chuyển từ việc sắp đặt các bóng bán dẫn, đến
các phần tử logic và các khối logic.
| Tương tự như vậy, việc thiết kế kiến trúc các mạng nơ-ron đã phát
triển theo hướng ngày một trừu tượng hơn. Điển hình là việc các nhà
nghiên cứu đã thay đổi suy nghĩ từ quy mô các nơ-ron riêng lẻ sang các
tầng, và giờ đây là các khối chứa các tầng lặp lại theo khuôn mẫu.
.. raw:: html
Ý tưởng sử dụng các khối lần đầu xuất hiện trong mạng VGG, được đặt theo
tên của nhóm `VGG `__ thuộc Đại học
Oxford. Sử dụng bất kỳ các framework học sâu hiện đại nào với vòng lặp
và chương trình con để xây dựng các cấu trúc lặp lại này là tương đối dễ
dàng.
.. raw:: html
Khối VGG
--------
.. raw:: html
Khối cơ bản của mạng tích chập cổ điển là một chuỗi các tầng sau đây:
(i) một tầng tích chập (với phần đệm để duy trì độ phân giải), (ii) một
tầng phi tuyến như ReLU, (iii) một tầng gộp như tầng gộp cực đại. Một
khối VGG gồm một chuỗi các tầng tích chập, tiếp nối bởi một tầng gộp cực
đại để giảm chiều không gian. Trong bài báo gốc của VGG
:cite:`Simonyan.Zisserman.2014`, tác giả sử dụng tích chập với các hạt
nhân :math:`3\times3` và tầng gộp cực đại :math:`2 \times 2` với sải
bước bằng :math:`2` (giảm một nửa độ phân giải sau mỗi khối). Trong mã
nguồn dưới đây, ta định nghĩa một hàm tên ``vgg_block`` để tạo một khối
VGG. Hàm này nhận hai đối số ``num_convs`` và ``num_channels`` tương ứng
lần lượt với số tầng tích chập và số kênh đầu ra.
.. code:: python
from d2l import mxnet as d2l
from mxnet import np, npx
from mxnet.gluon import nn
npx.set_np()
def vgg_block(num_convs, num_channels):
blk = nn.Sequential()
for _ in range(num_convs):
blk.add(nn.Conv2D(num_channels, kernel_size=3,
padding=1, activation='relu'))
blk.add(nn.MaxPool2D(pool_size=2, strides=2))
return blk
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
.. raw:: html
Mạng VGG
--------
.. raw:: html
Giống như AlexNet và LeNet, mạng VGG có thể được phân chia thành hai
phần: phần đầu tiên bao gồm chủ yếu các tầng tích chập và tầng gộp, còn
phần thứ hai bao gồm các tầng kết nối đầy đủ. Phần tích chập của mạng
gồm các mô-đun ``vgg_block`` kết nối liên tiếp với nhau. Trong
:numref:`fig_vgg`, biến ``conv_arch`` bao gồm một danh sách các tuples
(một tuple cho mỗi khối), trong đó mỗi tuple chứa hai giá trị: số lượng
tầng tích chập và số kênh đầu ra, cũng chính là những đối số cần thiết
để gọi hàm ``vgg_block``. Mô-đun kết nối đầy đủ giống hệt với mô-đun
tương ứng trong AlexNet.
.. raw:: html
.. _fig_vgg:
.. figure:: ../img/vgg.svg
:width: 400px
Thiết kế mạng từ các khối cơ bản
.. raw:: html
Mạng VGG gốc có 5 khối tích chập, trong đó hai khối đầu tiên bao gồm một
tầng tích chập ở mỗi khối, ba khối còn lại chứa hai tầng tích chập ở mỗi
khối. Khối đầu tiên có 64 kênh đầu ra, mỗi khối tiếp theo nhân đôi số
kênh đầu ra cho tới khi đạt giá trị :math:`512`. Vì mạng này sử dụng
:math:`8` tầng tích chập và :math:`3` tầng kết nối đầy đủ nên nó thường
được gọi là VGG-11.
.. code:: python
conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
.. raw:: html
Đoạn mã nguồn sau đây lập trình mạng VGG-11. Ở đây ta chỉ đơn thuần thực
hiện vòng lặp ``for`` trên biến ``conv_arch``.
.. code:: python
def vgg(conv_arch):
net = nn.Sequential()
# The convolutional layer part
for (num_convs, num_channels) in conv_arch:
net.add(vgg_block(num_convs, num_channels))
# The fully connected layer part
net.add(nn.Dense(4096, activation='relu'), nn.Dropout(0.5),
nn.Dense(4096, activation='relu'), nn.Dropout(0.5),
nn.Dense(10))
return net
net = vgg(conv_arch)
.. raw:: html
Tiếp theo, chúng ta sẽ tạo một mẫu dữ liệu một kênh với chiều cao và
chiều rộng là 224 để quan sát kích thước đầu ra của mỗi tầng.
.. code:: python
net.initialize()
X = np.random.uniform(size=(1, 1, 224, 224))
for blk in net:
X = blk(X)
print(blk.name, 'output shape:\t', X.shape)
.. parsed-literal::
:class: output
sequential1 output shape: (1, 64, 112, 112)
sequential2 output shape: (1, 128, 56, 56)
sequential3 output shape: (1, 256, 28, 28)
sequential4 output shape: (1, 512, 14, 14)
sequential5 output shape: (1, 512, 7, 7)
dense0 output shape: (1, 4096)
dropout0 output shape: (1, 4096)
dense1 output shape: (1, 4096)
dropout1 output shape: (1, 4096)
dense2 output shape: (1, 10)
.. raw:: html
Như bạn thấy, ta đã giảm chiều cao và chiều rộng đi một nửa sau mỗi
khối, cuối cùng kích thước của các biễu diễn chỉ còn là 7 trên mỗi chiều
trước khi được trải phẳng ra để tiếp tục xử lý trong tầng kết nối đầy
đủ.
.. raw:: html
.. raw:: html
.. raw:: html
Huấn luyện Mô hình
------------------
.. raw:: html
Vì VGG-11 thực hiện nhiều tính toán hơn AlexNet, ta sẽ xây dựng một mạng
với số kênh nhỏ hơn. Như vậy vẫn là quá đủ để huấn luyện trên bộ dữ liệu
Fashion-MNIST.
.. code:: python
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)
.. raw:: html
Ngoại trừ việc sử dụng tốc độ học lớn hơn một chút, quy trình huấn luyện
mô hình này tương tự như của AlexNet trong phần trước.
.. code:: python
lr, num_epochs, batch_size = 0.05, 10, 128,
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr)
.. parsed-literal::
:class: output
loss 0.175, train acc 0.935, test acc 0.929
872.7 examples/sec on gpu(0)
.. figure:: output_vgg_vn_7498b1_11_1.svg
.. raw:: html
Tóm tắt
-------
.. raw:: html
- Mạng VGG-11 được xây dựng bằng cách tái sử dụng các khối tích chập.
Các mô hình VGG khác nhau có thể được định nghĩa bằng cách thay đổi
số lượng các tầng tích chập và số kênh đầu ra ở mỗi khối.
- Việc sử dụng các khối giúp ta định nghĩa mạng bằng các đoạn mã nguồn
ngắn gọn và thiết kế các mạng phức tạp một cách hiệu quả hơn.
- Thử nghiệm nhiều kiến trúc khác nhau, Simonyan và Zisserman đã phát
hiện rằng mạng có cửa sổ tích chập hẹp (như :math:`3 \times 3`) và
nhiều tầng cho hiệu quả cao hơn mạng có cửa sổ tích chập rộng nhưng
ít tầng.
.. raw:: html
Bài tập
-------
.. raw:: html
1. Khi in ra kích thước của các tầng, chúng ta chỉ thấy 8 kết quả chứ
không phải 11. Thông tin về 3 tầng còn lại nằm ở đâu?
2. So với AlexNet, VGG chậm hơn đáng kể về mặt tính toán và cũng đòi hỏi
nhiều bộ nhớ GPU hơn. Hãy phân tích lý do cho hiện tượng này?
3. Thử thay đổi chiều cao vầ chiều rộng của các ảnh trong Fashion-MNIST
từ 224 xuống 96. Điều này ảnh hưởng thế nào tới các thử nghiệm?
4. Tham khảo Bảng 1 trong :cite:`Simonyan.Zisserman.2014` để xây dựng
các mô hình thông dụng khác, ví dụ như là VGG-16 và VGG-19.
.. raw:: html
.. raw:: html
Thảo luận
---------
- `Tiếng Anh `__
- `Tiếng Việt `__
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
- Lê Khắc Hồng Phúc
- Phạm Minh Đức
- Nguyễn Văn Cường
- Nguyễn Văn Quang
- Nguyễn Cảnh Thướng