????????论文地址:NIN(Network In Network,网络中的网络),字面意思是嵌套很多网络模块(微小网络),这种网络模型的结构是将多层感知机(Multilayer Perceptron,MLP)和卷积层结合在一起,用多层感知器去实例化微小网络,是一种强有效的函数逼近器,将这样的结构进行堆叠,就实现了深度的NIN,再跟随一个最大池化层,把原本输入样本减少一半。
????????最后在Softmax分类层的特征图上利用全局平均池化(Global Average Pooling,GAP)得到的输入,可以很好的获取所有特征图信息,使得空间转换变得更加鲁棒。 ????????其次全局平均池化层替换了全连接层,我们知道在 MXNet多通道的输入与多通道的输出,1x1的卷积 使用1*1卷积核可以等价于全连接层,这样替换的好处是模型不容易过拟合,而且对于输入的图像尺寸没有固定要求。论文也指出GAP容易解释和理解分类与特征图之间的一致性,而全连接层看起来就像一个“黑盒”,不容易理解,还非常依赖Dropout正则化。 如下图包含三个MLPCONV层加一个GAP层的NIN,在每个MLPCONV层中,有一个三层的感知器,其中NIN和微小网络的层数都可以自己调整的,比较灵活。
构建NiN块
NiN块类似于VGG块(对VGGNet的实现(3*3卷积核的重复运用)) 一个自行设置超参数的卷积层加两个固定超参数的1*1的卷积层(等价于全连接层)
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
这样一个nin块就完成了,既然是NIN网络模型,那么就会存在很多这样的块的堆叠,我们可以像以前一样构建网络模型,在模型里面添加这样的nin块即可,
构建NIN模型
import d2lzh as d2l
from mxnet import gluon,init,nd
from mxnet.gluon import nn
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
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),
nin_block(10,kernel_size=3,strides=1,padding=1),
#全局平均池化可以将窗口形状自动设置为输入的高和宽
nn.GlobalAvgPool2D(),
#四维输出转成二维输出,形状为(批量大小,10)
nn.Flatten())
#观察每层的输出形状
X=nd.random.uniform(shape=(5,1,224,224))
net.initialize()
for n in net:
X=n(X)
print(n.name,'输出形状:',X.shape)
'''
sequential1 输出形状: (5, 96, 54, 54)
pool0 输出形状: (5, 96, 26, 26)
sequential2 输出形状: (5, 256, 26, 26)
pool1 输出形状: (5, 256, 12, 12)
sequential3 输出形状: (5, 384, 12, 12)
pool2 输出形状: (5, 384, 5, 5)
dropout0 输出形状: (5, 384, 5, 5)
sequential4 输出形状: (5, 10, 5, 5)
pool3 输出形状: (5, 10, 1, 1)
flatten0 输出形状: (5, 10)
'''
训练模型
我们还是使用Fashion-MNIST数据集来训练,可以对比下VGG,代码如下:
#训练模型(使用Fashion-MNIST数据集)
lr,num_epochs,batch_size,ctx=0.1,5,128,d2l.try_gpu()
net.initialize(force_reinit=True,ctx=ctx,init=init.Xavier())
trainer=gluon.Trainer(net.collect_params(),'sgd',{'learning_rate':lr})
train_iter,test_iter=d2l.load_data_fashion_mnist(batch_size,resize=96)#224内存溢出
d2l.train_ch5(net,train_iter,test_iter,batch_size,trainer,ctx,num_epochs)
'''
epoch 1, loss 2.0787, train acc 0.254, test acc 0.514, time 40.4 sec
epoch 2, loss 1.2241, train acc 0.555, test acc 0.664, time 37.9 sec
epoch 3, loss 0.9790, train acc 0.644, test acc 0.669, time 38.2 sec
epoch 4, loss 0.9049, train acc 0.679, test acc 0.703, time 38.2 sec
epoch 5, loss 0.8572, train acc 0.708, test acc 0.748, time 38.3 sec
'''
|