43. 网络中的网络(NiN)代码实现

1. NiN块

NiN块以一个普通卷积层开始,后面是两个 1×1 的卷积层。这两个 1×1 卷积层充当带有ReLU激活函数的逐像素全连接层。 第一层的卷积窗口形状通常由用户设置。 随后的卷积窗口形状固定为 1×1 。

import torch
from torch import nn
from d2l import torch as d2l

# nin_block函数中的kernel_size是第一个卷积窗口大小,由用户指定
# 之后的两个固定了是1*1
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())

2. NiN模型

最初的NiN网络是在AlexNet后不久提出的,显然从中得到了一些启示。

NiN使用窗口形状为 11×11 、 5×5 和 3×3 的卷积层,输出通道数量与AlexNet中的相同。 每个NiN块后有一个最大汇聚层,汇聚窗口形状为 3×3 ,步幅为2

NiN和AlexNet之间的一个显著区别是NiN完全取消了全连接层。 相反,NiN使用一个NiN块,其输出通道数等于标签类别的数量。最后放一个全局平均汇聚层(global average pooling layer),生成一个对数几率 (logits)。

NiN设计的一个优点是,它显著减少了模型所需参数的数量。然而,在实践中,这种设计有时会增加训练模型的时间。

net = nn.Sequential(
    nin_block(1, 96, kernel_size=11, strides=4, padding=0), # 输入通道是1,因为是灰度图
    nn.MaxPool2d(3, stride=2), # maxpooling是减小特征图尺寸,高宽减半,不改变通道数
    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,因为标签类别数是10,如果用别的数据集,要将其改成别的number of class
    nin_block(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)), # AdaptiveAvgPool2d全集的平均池化层
    # 将四维的输出转成二维的输出,其形状为(批量大小,10)
    nn.Flatten())

3. 查看每个块的输出形状

X = torch.rand(size=(1, 1, 224, 224))
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape:\t', X.shape)

43. 网络中的网络(NiN)代码实现_第1张图片
可以看出,原始输入是一个大小为 224 * 224的灰度图片,这张图片通过模型会得到一个长为10的向量,10是类别的个数。

4. 训练模型

和以前一样,我们使用Fashion-MNIST来训练模型。训练NiN与训练AlexNet、VGG时相似。

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())

43. 网络中的网络(NiN)代码实现_第2张图片

5. 一些Q&A

Q1: 这里做10个分类,不需要softmax吗?
A1:这里分类是要做softmax的,只是softmax没有写在net里面,而是写在了train_ch6这个函数里面。

nn.CrossEntropyLoss()这个损失函数用于多分类问题虽然说的是交叉熵,但是和我理解的交叉熵不一样。nn.CrossEntropyLoss()是nn.logSoftmax()和nn.NLLLoss()的整合,可以直接使用它来替换网络中的这两个操作。

由此也可以看出,所有的卷积神经网络都没有softmax在里面。

43. 网络中的网络(NiN)代码实现_第3张图片
Q2:全局平均汇聚层的作用。
A2:全局平均汇聚层把卷积的输出的高宽压成了1 * 1,主要的效果就是把输出变小了,且没有可学习的参数,主要的好处是把模型复杂度降低了,是一个很强的降低模型复杂度的操作。而且发现,加入全局平均汇聚层后,模型的泛化性会更好,让精度更好。

但是也有坏处:使得收敛变慢。

而AlexNet和VGG收敛快,就是因为后面两个全连接层(Dense层)很强,很容易去fit数据。

43. 网络中的网络(NiN)代码实现_第4张图片

你可能感兴趣的:(深度学习,网络,深度学习,python)