经典神经网络(4)Nin-Net及其在Fashion-MNIST数据集上的应用
1 Nin-Net的简述
1.1 Nin-Net的概述
LeNet、AlexNet和VGG都有⼀个共同的设计模式:通过⼀系列的卷积层与汇聚层来提取空间结构特征;然后通过全连接层对特征的表征进⾏处理。AlexNet和VGG对LeNet的改进主要在于如何扩⼤和加深这两个模块。
然⽽,如果使⽤了全连接层,可能会完全放弃表征的空间结构。⽹络中的⽹络(NiN)提供了⼀个⾮常简单的解决⽅案:在每个像素的通道上分别使⽤多层感知机。
NiN的想法是在每个像素位置(针对每个⾼度和宽度)应⽤⼀个全连接层。如果我们将权重连接到每个空间位置,我们可以将其视为1 *×* 1卷积层,或作为在每个像素位置上独⽴作⽤的全连接层。从另⼀个⻆度看,即将空间维度中的每个像素视为单个样本,将通道维度视为不同特征(feature)
。
1.2 Nin-Net的实现
import torch.nn as nn
import torch
class NinNet(nn.Module):
def __init__(self):
super().__init__()
'''
最初的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设计的⼀个优点是,它显著减少了模型所需参数的数量。然⽽,在实践中,这种设计有时会增加训练模
型的时间。
'''
self.model = nn.Sequential(
self.nin_block(in_channels=1,out_channels=96,kernel_size=11,strides=4,padding=0),
nn.MaxPool2d(kernel_size=3,stride=2),
self.nin_block(in_channels=96, out_channels=256, kernel_size=5, strides=1, padding=2),
nn.MaxPool2d(kernel_size=3, stride=2),
self.nin_block(in_channels=256, out_channels=384, kernel_size=3, strides=1, padding=1),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Dropout(0.5),
# 标签类别数是10
self.nin_block(384, 10, kernel_size=3, strides=1, padding=1),
nn.AdaptiveAvgPool2d((1, 1)),
# 将四维的输出转成二维的输出,其形状为(批量⼤⼩,10)
nn.Flatten()
)
def forward(self, X):
X = self.model(X)
return X
def nin_block(self,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()
)
if __name__ == '__main__':
net = NinNet()
# 测试神经网络是否可运行
# inputs = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32)
# outputs = net(inputs)
# print(outputs.shape)
X = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32)
for layer in net.model:
X = layer(X)
print(layer.__class__.__name__, 'output shape:', 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])
# 全局平均汇聚层(global average pooling layer)
AdaptiveAvgPool2d output shape: torch.Size([1, 10, 1, 1])
Flatten output shape: torch.Size([1, 10])
2 Nin-Net在Fashion-MNIST数据集上的应用示例
3.1 创建Nin-Net网络模型
如1.2代码所示。
3.2 读取Fashion-MNIST数据集
其他所有的函数,与经典神经网络(1)LeNet及其在Fashion-MNIST数据集上的应用完全一致。
batch_size = 128
train_iter,test_iter = get_mnist_data(batch_size,resize=224)
3.3 在GPU上进行模型训练
from _04_NinNet import NinNet
# 初始化模型
net = NinNet()
lr, num_epochs = 0.1, 10
train_ch(net, train_iter, test_iter, num_epochs, lr, try_gpu())