26 网络中的网络 NiN【动手学深度学习v2】

Net in Net,一种现在比较冷门的网络结构
在常用的网络中,全连接层的存在往往会使要训练的参数爆炸增长。
NiN思想:完全抛弃全连接层

在NiN中,最重要的结构是NiN块(大部分经典网络结构的主要组成部分都是各种网络块)
NiN块主要由一个卷积层和两个1*1全连接层组成(也可视为1*1卷积层),相当于一个参数减少了的全连接层。

NiN架构:交替使用NiN块和二步最大池化层



NiN块以一个普通卷积层开始,后面是两个1×1
的卷积层。这两个1×1卷积层充当带有ReLU激活函数的逐像素全连接层。 第一层的卷积窗口形状通常由用户设置。 随后的卷积窗口形状固定为1×1。
代码实现:
构建NiN块:
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())
由上述代码可以看出,一个NiN块中含有三个ReLU,NiN的非线性拟合主要是ReLU带来的
构建网络:
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), # 标签类别数是10 nin_block(384, 10, kernel_size=3, strides=1, padding=1), nn.AdaptiveAvgPool2d((1, 1)), #AdaptiveAvgPool2d:全局平均池化 # 将四维的输出转成二维的输出,其形状为(批量大小,10),这个数据可以直接输入softmax进行最大似然估计,softmax已经写在train函数里了 nn.Flatten())
创建一个数据样本来查看每个块的输出形状。
X = torch.rand(size=(1, 1, 224, 224)) for layer in net: X = layer(X) print(layer.__class__.__name__,'output shape:\t', X.shape)
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])
训练效果
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())
loss 0.322, train acc 0.881, test acc 0.865 3226.1 examples/sec on cuda:0