.. _sec_nin: Mạng trong mạng (Nin) ===================== LeNet, AlexNet và VGG đều chia sẻ một mẫu thiết kế chung: trích xuất các tính năng khai thác cấu trúc *không gian* thông qua một chuỗi các lớp phức tạp và tập hợp và sau đó xử lý các biểu diễn thông qua các lớp được kết nối hoàn toàn. Những cải tiến trên LeNet của AlexNet và VGG chủ yếu nằm ở cách các mạng sau này mở rộng và làm sâu sắc thêm hai mô-đun này. Ngoài ra, người ta có thể tưởng tượng sử dụng các lớp được kết nối hoàn toàn trước đó trong quá trình này. Tuy nhiên, việc sử dụng bất cẩn các lớp dày đặc có thể từ bỏ cấu trúc không gian của biểu diễn hoàn toàn, *mạng trong mạng* (\* NiN\*) khối cung cấp một giải pháp thay thế. Chúng được đề xuất dựa trên một cái nhìn sâu sắc rất đơn giản: sử dụng MLP trên các kênh cho mỗi pixel riêng biệt :cite:`Lin.Chen.Yan.2013`. NiN Blocks ---------- Nhớ lại rằng các đầu vào và đầu ra của các lớp phức tạp bao gồm các hàng chục bốn chiều với các trục tương ứng với ví dụ, kênh, chiều cao và chiều rộng. Cũng nhớ lại rằng các đầu vào và đầu ra của các lớp được kết nối hoàn toàn thường là các hàng chục hai chiều tương ứng với ví dụ và tính năng. Ý tưởng đằng sau Nin là áp dụng một lớp được kết nối hoàn toàn tại mỗi vị trí pixel (cho mỗi chiều cao và chiều rộng). Nếu chúng ta buộc trọng lượng trên mỗi vị trí không gian, chúng ta có thể nghĩ đây là một lớp ghép :math:`1\times 1` (như được mô tả trong :numref:`sec_channels`) hoặc như một lớp được kết nối hoàn toàn hoạt động độc lập trên mỗi vị trí pixel. Một cách khác để xem điều này là nghĩ về từng phần tử trong chiều không gian (chiều cao và chiều rộng) tương đương với một ví dụ và một kênh tương đương với một đối tượng. :numref:`fig_nin` minh họa sự khác biệt về cấu trúc chính giữa VGG và Nin, và các khối của chúng. Khối Nin bao gồm một lớp phức tạp tiếp theo là hai lớp ghép :math:`1\times 1` hoạt động như các lớp được kết nối hoàn toàn trên mỗi pixel với các kích hoạt ReLU. Hình dạng cửa sổ phức tạp của lớp đầu tiên thường được đặt bởi người dùng. Các hình dạng cửa sổ tiếp theo được cố định thành :math:`1 \times 1`. .. _fig_nin: .. figure:: ../img/nin.svg :width: 600px Comparing architectures of VGG and NiN, and their blocks. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python from mxnet import np, npx from mxnet.gluon import nn from d2l import mxnet as d2l npx.set_np() def nin_block(num_channels, kernel_size, strides, padding): blk = nn.Sequential() blk.add(nn.Conv2D(num_channels, kernel_size, strides, padding, activation='relu'), nn.Conv2D(num_channels, kernel_size=1, activation='relu'), nn.Conv2D(num_channels, kernel_size=1, activation='relu')) return blk .. raw:: html
.. raw:: html
.. code:: python import torch from torch import nn from d2l import torch as d2l def nin_block(in_channels, out_channels, kernel_size, strides, padding): return nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding), nn.ReLU(), nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(), nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU()) .. raw:: html
.. raw:: html
.. code:: python import tensorflow as tf from d2l import tensorflow as d2l def nin_block(num_channels, kernel_size, strides, padding): return tf.keras.models.Sequential([ tf.keras.layers.Conv2D(num_channels, kernel_size, strides=strides, padding=padding, activation='relu'), tf.keras.layers.Conv2D(num_channels, kernel_size=1, activation='relu'), tf.keras.layers.Conv2D(num_channels, kernel_size=1, activation='relu')]) .. raw:: html
.. raw:: html
Mô hình NiN ----------- Mạng Nin ban đầu được đề xuất ngay sau AlexNet và rõ ràng rút ra một số cảm hứng. Nin sử dụng các lớp phức tạp với hình dạng cửa sổ :math:`11\times 11`, :math:`5\times 5`, và :math:`3\times 3`, và các số kênh đầu ra tương ứng giống như trong AlexNet. Mỗi khối Nin được theo sau bởi một lớp tổng hợp tối đa với một sải chân là 2 và một hình dạng cửa sổ là :math:`3\times 3`. Một điểm khác biệt đáng kể giữa Nin và AlexNet là Nin tránh hoàn toàn các lớp được kết nối hoàn toàn. Thay vào đó, Nin sử dụng một khối Nin với một số kênh đầu ra bằng số lớp nhãn, tiếp theo là một lớp tổng hợp trung bình *global*, mang lại một vectơ của logits. Một ưu điểm của thiết kế của Nin là nó làm giảm đáng kể số lượng các thông số mô hình cần thiết. Tuy nhiên, trong thực tế, thiết kế này đôi khi đòi hỏi thời gian đào tạo mô hình tăng lên. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python net = nn.Sequential() net.add(nin_block(96, kernel_size=11, strides=4, padding=0), nn.MaxPool2D(pool_size=3, strides=2), nin_block(256, kernel_size=5, strides=1, padding=2), nn.MaxPool2D(pool_size=3, strides=2), nin_block(384, kernel_size=3, strides=1, padding=1), nn.MaxPool2D(pool_size=3, strides=2), nn.Dropout(0.5), # There are 10 label classes nin_block(10, kernel_size=3, strides=1, padding=1), # The global average pooling layer automatically sets the window shape # to the height and width of the input nn.GlobalAvgPool2D(), # Transform the four-dimensional output into two-dimensional output # with a shape of (batch size, 10) nn.Flatten()) .. raw:: html
.. raw:: html
.. code:: python net = nn.Sequential( nin_block(1, 96, kernel_size=11, strides=4, padding=0), nn.MaxPool2d(3, stride=2), nin_block(96, 256, kernel_size=5, strides=1, padding=2), nn.MaxPool2d(3, stride=2), nin_block(256, 384, kernel_size=3, strides=1, padding=1), nn.MaxPool2d(3, stride=2), nn.Dropout(0.5), # There are 10 label classes nin_block(384, 10, kernel_size=3, strides=1, padding=1), nn.AdaptiveAvgPool2d((1, 1)), # Transform the four-dimensional output into two-dimensional output with a # shape of (batch size, 10) nn.Flatten()) .. raw:: html
.. raw:: html
.. code:: python def net(): return tf.keras.models.Sequential([ nin_block(96, kernel_size=11, strides=4, padding='valid'), tf.keras.layers.MaxPool2D(pool_size=3, strides=2), nin_block(256, kernel_size=5, strides=1, padding='same'), tf.keras.layers.MaxPool2D(pool_size=3, strides=2), nin_block(384, kernel_size=3, strides=1, padding='same'), tf.keras.layers.MaxPool2D(pool_size=3, strides=2), tf.keras.layers.Dropout(0.5), # There are 10 label classes nin_block(10, kernel_size=3, strides=1, padding='same'), tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Reshape((1, 1, 10)), # Transform the four-dimensional output into two-dimensional output # with a shape of (batch size, 10) tf.keras.layers.Flatten(), ]) .. raw:: html
.. raw:: html
Chúng ta tạo ra một ví dụ dữ liệu để xem hình dạng đầu ra của mỗi block. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python X = np.random.uniform(size=(1, 1, 224, 224)) net.initialize() for layer in net: X = layer(X) print(layer.name, 'output shape:\t', X.shape) .. parsed-literal:: :class: output sequential1 output shape: (1, 96, 54, 54) pool0 output shape: (1, 96, 26, 26) sequential2 output shape: (1, 256, 26, 26) pool1 output shape: (1, 256, 12, 12) sequential3 output shape: (1, 384, 12, 12) pool2 output shape: (1, 384, 5, 5) dropout0 output shape: (1, 384, 5, 5) sequential4 output shape: (1, 10, 5, 5) pool3 output shape: (1, 10, 1, 1) flatten0 output shape: (1, 10) .. raw:: html
.. raw:: html
.. code:: python X = torch.rand(size=(1, 1, 224, 224)) for layer in net: X = layer(X) print(layer.__class__.__name__,'output shape:\t', X.shape) .. parsed-literal:: :class: output Sequential output shape: torch.Size([1, 96, 54, 54]) MaxPool2d output shape: torch.Size([1, 96, 26, 26]) Sequential output shape: torch.Size([1, 256, 26, 26]) MaxPool2d output shape: torch.Size([1, 256, 12, 12]) Sequential output shape: torch.Size([1, 384, 12, 12]) MaxPool2d output shape: torch.Size([1, 384, 5, 5]) Dropout output shape: torch.Size([1, 384, 5, 5]) Sequential output shape: torch.Size([1, 10, 5, 5]) AdaptiveAvgPool2d output shape: torch.Size([1, 10, 1, 1]) Flatten output shape: torch.Size([1, 10]) .. raw:: html
.. raw:: html
.. code:: python X = tf.random.uniform((1, 224, 224, 1)) for layer in net().layers: X = layer(X) print(layer.__class__.__name__,'output shape:\t', X.shape) .. parsed-literal:: :class: output Sequential output shape: (1, 54, 54, 96) MaxPooling2D output shape: (1, 26, 26, 96) Sequential output shape: (1, 26, 26, 256) MaxPooling2D output shape: (1, 12, 12, 256) Sequential output shape: (1, 12, 12, 384) MaxPooling2D output shape: (1, 5, 5, 384) Dropout output shape: (1, 5, 5, 384) Sequential output shape: (1, 5, 5, 10) GlobalAveragePooling2D output shape: (1, 10) Reshape output shape: (1, 1, 1, 10) Flatten output shape: (1, 10) .. raw:: html
.. raw:: html
Đào tạo ------- Như trước đây chúng ta sử dụng Fashion-MNIST để đào tạo mô hình. Đào tạo của Nin tương tự như cho AlexNet và VGG. .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
.. code:: python lr, num_epochs, batch_size = 0.1, 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, d2l.try_gpu()) .. parsed-literal:: :class: output loss 1.843, train acc 0.316, test acc 0.568 2926.6 examples/sec on gpu(0) .. figure:: output_nin_8ad4f3_39_1.svg .. raw:: html
.. raw:: html
.. code:: python lr, num_epochs, batch_size = 0.1, 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, d2l.try_gpu()) .. parsed-literal:: :class: output loss 0.381, train acc 0.858, test acc 0.863 3160.4 examples/sec on cuda:0 .. figure:: output_nin_8ad4f3_42_1.svg .. raw:: html
.. raw:: html
.. code:: python lr, num_epochs, batch_size = 0.1, 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, d2l.try_gpu()) .. parsed-literal:: :class: output loss 0.336, train acc 0.874, test acc 0.876 3264.0 examples/sec on /GPU:0 .. parsed-literal:: :class: output .. figure:: output_nin_8ad4f3_45_2.svg .. raw:: html
.. raw:: html
Tóm tắt ------- - Nin sử dụng các khối bao gồm một lớp phức tạp và nhiều lớp ghép :math:`1\times 1`. Điều này có thể được sử dụng trong ngăn xếp phức tạp để cho phép tính phi tuyến trên mỗi pixel hơn. - Nin loại bỏ các lớp được kết nối hoàn toàn và thay thế chúng bằng tổng hợp trung bình toàn cầu (tức là tổng hợp tất cả các vị trí) sau khi giảm số lượng kênh xuống số lượng đầu ra mong muốn (ví dụ: 10 cho Fashion-MNIST). - Loại bỏ các lớp được kết nối hoàn toàn làm giảm quá mức. Nin có ít tham số hơn đáng kể. - Thiết kế Nin ảnh hưởng đến nhiều thiết kế CNN tiếp theo. Bài tập ------- 1. Điều chỉnh các siêu tham số để cải thiện độ chính xác phân loại. 2. Tại sao có hai lớp ghép :math:`1\times 1` trong khối Nin? Loại bỏ một trong số chúng, sau đó quan sát và phân tích các hiện tượng thử nghiệm. 3. Tính toán mức sử dụng tài nguyên cho Nin. 1. Số lượng tham số là bao nhiêu? 2. Số lượng tính toán là bao nhiêu? 3. Dung lượng bộ nhớ cần thiết trong quá trình đào tạo là bao nhiêu? 4. Dung lượng bộ nhớ cần thiết trong quá trình dự đoán là bao nhiêu? 4. Những vấn đề có thể xảy ra với việc giảm đại diện :math:`384 \times 5 \times 5` thành đại diện :math:`10 \times 5 \times 5` trong một bước là gì? .. raw:: html
mxnetpytorchtensorflow
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html
`Discussions `__ .. raw:: html
.. raw:: html