【深度学习】NIN网络中的网络(pyTorch)

1 Introduction

LeNet、AlexNet和VGG在设计上的共同之处是:先以由卷积层构成的模块充分抽取空间特征,再以由全连接层构成的模块来输出分类结果。

其中,AlexNet和VGG对LeNet的改进主要在于如何对这两个模块加宽(增加通道数)和加深。

而网络中的网络(NiN)提出了另外一个思路,即串联多个由卷积层和“全连接”层构成的小网络来构建一个深层网络。

1×1卷积层可以看成全连接层,其中空间维度(高和宽)上的每个元素相当于样本,通道相当于特征。因此,NiN使用1×1卷积层来替代全连接层,从而使空间特征信息能够自然传递到后面的层中去。

2 NIN块

NiN块是NiN中的基础块。它由一个卷积层加两个充当全连接层的1×1卷积层串联而成。其中第一个卷积层的超参数可以自行设置,而第二和第三个卷积层的超参数一般是固定的。

import time
import torch 
from torch import nn, optim
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l
device = torch.device('cuda' if torch.cuda.is_available else 'cpu')

def nin_block(in_channels, out_channels, kernel_size, stride, padding):
    blk = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding),
            nn.ReLU(),
        
            nn.Conv2d(out_channels, out_channels, 1, 1, 1),
            nn.ReLU(),
        
            nn.Conv2d(out_channels, out_channels, 1, 1, 1),
            nn.ReLU()
    )
    return blk

3 NIN模型

NiN使用卷积窗口形状分别为11×11、5×5和3×3的卷积层,相应的输出通道数与AlexNet中的一致。每个NiN块后接一个步幅为2、窗口形状为3×3的最大池化层。

除使用NiN块以外,NiN还有一个设计与AlexNet显著不同:NiN去掉了AlexNet最后的3个全连接层,取而代之地,NiN使用了输出通道数等于标签类别数的NiN块,然后使用全局平均池化层对每个通道中所有元素求平均并直接用于分类。这样可以显著减小模型参数尺寸,从而缓解过拟合,但会增加模型训练时间。

import torch.nn.functional as F
class GlobalAvgPool2d(nn.Module):
    # 全局平均池化层可通过将池化窗口形状设置成输入的高和宽实现
    def __init__(self):
        super(GlobalAvgPool2d, self).__init__()
    def forward(self, x):
        return F.avg_pool2d(x, kernel_size = x.size()[2:])

net = nn.Sequential(
        nin_block(1,96,  kernel_size=11, stride=4, padding=0),
        nn.MaxPool2d( kernel_size=3, stride=2),
        nin_block(96,256,  kernel_size=5, stride=1, padding=2),
        nn.MaxPool2d( kernel_size=3, stride=2),
        nin_block(256,384,  kernel_size=3, stride=1, padding=1),
        nn.MaxPool2d( kernel_size=3, stride=2),
        nn.Dropout(0.5),
    
        # 标签类别数是10
        nin_block(384, 10, kernel_size=3, stride=1, padding=1),
        GlobalAvgPool2d(), 
        # 将四维的输出转成二维的输出,其形状为(批量大小, 10)
        d2l.FlattenLayer()
)
X = torch.rand(1,1,224,224)
for name, blk in net.named_children():
    
    X = blk(X)
    
    print(name, 'output shape', X.shape)
0 output shape torch.Size([1, 96, 58, 58])
1 output shape torch.Size([1, 96, 28, 28])
2 output shape torch.Size([1, 256, 32, 32])
3 output shape torch.Size([1, 256, 15, 15])
4 output shape torch.Size([1, 384, 19, 19])
5 output shape torch.Size([1, 384, 9, 9])
6 output shape torch.Size([1, 384, 9, 9])
7 output shape torch.Size([1, 10, 13, 13])
8 output shape torch.Size([1, 10, 1, 1])
9 output shape torch.Size([1, 10])

4 获取数据和训练模型

batch_size = 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize = 224)

lr, num_epochs = 0.002, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device,num_epochs )
training on  cuda
epoch 1, loss 1.8106, train acc 0.372, test acc 0.573, time 634.8 sec
epoch 2, loss 0.5976, train acc 0.641, test acc 0.655, time 651.8 sec
epoch 3, loss 0.3558, train acc 0.682, test acc 0.686, time 688.2 sec
epoch 4, loss 0.2231, train acc 0.700, test acc 0.711, time 698.2 sec
epoch 5, loss 0.1489, train acc 0.732, test acc 0.744, time 684.7 sec

Hints:

NiN重复使用由卷积层和代替全连接层的1×11×1卷积层构成的NiN块来构建深层网络。

NiN去除了容易造成过拟合的全连接输出层,而是将其替换成输出通道数等于标签类别数的NiN块和全局平均池化层。

NiN的以上设计思想影响了后面一系列卷积神经网络的设计。

参考原文:《动手学深度学习(pyTorch)》

欢迎关注【OAOA

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值