你不知道的NIN,及其它的pytorch实现

NIN(Network in Network)

正如它的名字所示,代表着网络中的网络。
它发表于2013年,入选国际学习表征会议ICLR 2014
优秀论文,其通过少量参数的深度学习模型轻松击败了AlexNet;
这也对我们电脑配置不高的人来说,算是一个特别友好的模型,不需要太大显存量就可训练一个较好的模型。
在这里插入图片描述

1.那为啥它的模型参数量少呢?

其实是因为它最后没有全连接层,大家应该知道,全连接层的参数量会特别大,训练时会耗费很大时间在全连接层上面,这些参数也会占用很多内存,让你本来就少的可怜的内存雪上加霜。

2.那它拿啥来取代全连接层呢?

它最后用到了一个全局平均池化(Global Average Pooling,GAP),会把所有特征图都变成1*1的,就是一个值,这不就能代表全连接层里边的一个神经元了么。

全局平均池化

和大家所熟知的池化操作一样,只不过它是把池化核的大小变的特征图大小相等,直接对所有值取平均值,得到这个平均值,作为输出。(这是不是一个很简单的操作呀)
在这里插入图片描述
就如上图所示,有几个特征图就得到几个输出值。

这样操作同时还有另一个好处,就是不用考虑输入的特征图有多大,到这里都不用计算特征图大小(如果我们使用全连接层,或者普通池化啥的,咱们是不是得往那个函数里边输特征图大小或者神经元个数,这得咱们计算吧,而且还对最初输入的图片大小有限制),可以直接经过这个函数得到输出值。

3.难道仅仅是因为参数量少了,它就可以达到这么好的效果吗?

当然不止这些啦!
它还有一个神奇的模块,叫MLP卷积(可不是感知机哦!)

MLP卷积

其实它就是一个1*1的卷积,就是叫了个高级的名字。
下面我们就说说这个1×1卷积到底有什么神奇的地方,可以让这个模型一下子跃到这么高的地位。

①参数量少,可以用来改变通道数

这个很明显,1×1的卷积核中的参数量是和特征图的通道数相等的,用它来改变通道数,相比那些大卷积核来说,是个不错的选择。

②可以增强模型的非线性拟合能力

大家要注意啊,每一个卷积操作后边,都会跟一个激活函数,多加几个1×1卷积,那不就意味着多增加了激活函数么,这不就提高了非线性拟合的能力。
大家可能会想,那用别的卷积核也行呀!相比1×1卷积,别的卷积核不是参数量大么,所以这又就显现出了它的第一条优势。

所以,该模型就多次使用到了1×1卷积,即很好的进行了通道信息的融合,又增强了非线性的拟合能力,这不是一举两得的事么。

NIN的pytorch实现

此处我是来做102分类任务的,所以到最后大家可以看到最后一个1×1卷积,输出通道为102。在这里插入图片描述

class NIN(nn.Module):
    def __init__(self):
        super().__init__()
        
        #每个Sequential里的计算量得一致,或相差不多,才能将GPU的利用率达到90%以上
        #in:512*512*3
        self.seq1 = nn.Sequential(
            nn.Conv2d(3,96,11,4),  #输入通道,输出通道,核大小,步长
            nn.BatchNorm2d(96),
            nn.ReLU(),
            #in:96*125*125
            nn.Conv2d(96,96,1),  #计算量:96*125*125*96
            nn.BatchNorm2d(96),
            nn.ReLU(),
            nn.Conv2d(96,96,1),
            nn.BatchNorm2d(96),
            nn.ReLU(),
            nn.MaxPool2d(3,2)
        )
        
        #in:96*62*62
        self.seq2 = nn.Sequential(
            nn.Conv2d(96,192,5,1,0),
            nn.BatchNorm2d(192),
            nn.ReLU(),
            #in:192*62*62
            nn.Conv2d(192,192,1),  #计算量:192*62*62*192
            nn.BatchNorm2d(192),
            nn.ReLU(),
            nn.Conv2d(192,192,1),
            nn.BatchNorm2d(192),
            nn.ReLU(),
            nn.MaxPool2d(3,2,0)
        )
        
        #in:192*31*31
        self.seq3 = nn.Sequential(
            nn.Conv2d(192,384,3,1,0),
            nn.BatchNorm2d(384),
            nn.ReLU(),
            #in:384*31*31
            nn.Conv2d(384,384,1),  #计算量:384*31*31*384
            nn.BatchNorm2d(384),
            nn.ReLU(),
            nn.Conv2d(384,384,1),
            nn.BatchNorm2d(384),
            nn.ReLU(),
            nn.MaxPool2d(3,2)
        )
        
        #in:384*15*15
        self.seq4 = nn.Sequential(
            nn.Conv2d(384,768,3,1,0),
            nn.BatchNorm2d(768),
            nn.ReLU(),
            #in:768*15*15
            nn.Conv2d(768,768,1),  #计算量:768*15*15*768
            nn.BatchNorm2d(768),
            nn.ReLU(),
            nn.Conv2d(768,102,1),  #做102分类,将输出特征层变为102
            nn.BatchNorm2d(102),
            nn.ReLU()
        )
        
        #全局平均池化
        self.p = nn.AdaptiveAvgPool2d((1,1)) 
        
    def forward(self, x):
        
        x = self.seq1(x)
        x = self.seq2(x)
        x = self.seq3(x)
        x = self.seq4(x)
        
        x = self.p(x)
        x = x.view(len(x),-1)
        return x
        

这里每个卷积的输出通道数,包括BN层,可能和原论文有出入,大家可以根据自己所做任务的实际情况更改。

希望可以帮助到大家,可以在评论区交流哦!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值