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())
最初的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())
X = torch.rand(size=(1, 1, 224, 224))
for layer in net:
X = layer(X)
print(layer.__class__.__name__,'output shape:\t', X.shape)
可以看出,原始输入是一个大小为 224 * 224的灰度图片,这张图片通过模型会得到一个长为10的向量,10是类别的个数。
和以前一样,我们使用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())
Q1: 这里做10个分类,不需要softmax吗?
A1:这里分类是要做softmax的,只是softmax没有写在net里面,而是写在了train_ch6这个函数里面。
nn.CrossEntropyLoss()这个损失函数用于多分类问题虽然说的是交叉熵,但是和我理解的交叉熵不一样。nn.CrossEntropyLoss()是nn.logSoftmax()和nn.NLLLoss()的整合,可以直接使用它来替换网络中的这两个操作。
由此也可以看出,所有的卷积神经网络都没有softmax在里面。
Q2:全局平均汇聚层的作用。
A2:全局平均汇聚层把卷积的输出的高宽压成了1 * 1,主要的效果就是把输出变小了,且没有可学习的参数,主要的好处是把模型复杂度降低了,是一个很强的降低模型复杂度的操作。而且发现,加入全局平均汇聚层后,模型的泛化性会更好,让精度更好。
但是也有坏处:使得收敛变慢。
而AlexNet和VGG收敛快,就是因为后面两个全连接层(Dense层)很强,很容易去fit数据。