秃姐学AI系列之:NiN + 代码实现

NiN-Network In Network:网络中的网络

现在已经很少使用了,但是提出来的一些概念到现在也被持续使用,所以还是很有了解到必要的

全连接层的问题

全连接层会带来巨大的参数空间,几乎整个网络的参数都集中在全连接层;

全连接层最重要的问题是:容易带来过拟合

卷积层只需要较少的参数:c_{i} x c_{o} x k^{2}

但卷积层后的第一个全连接层的参数:

  • LeNet:16x5x5x120 = 48k
  • AlexNet:256x5x5x4096 = 26M
  • VGG:512x7x7x4096 = 102M 

NiN 

为了解决这个问题——NiN的思路就是:完全不要全连接层! 

LeNet、AlexNet 和 VGG 都有一个共同的设计模式:

  1. 通过一系列的 卷积层 与 汇聚层 来提取空间结构特征;
  2. 然后通过全连接层对特征的表征进行处理。

AlexNet 和 VGG 对 LeNet 的改进主要在于如何扩大加深这两个模块。 或者,可以想象在这个过程的早期使用全连接层。

然而,如果使用了全连接层,可能会完全放弃表征的空间结构。 网络中的网络NiN)提供了一个非常简单的解决方案:在每个像素的通道上分别使用多层感知机

NiN块

一个卷积层后跟两个全连接层

  • 步幅1,无填充,输出形状跟卷积层输出一样
  • 起到全连接层的作用 

 我们知道1x1的卷积层可以等价于全连接层。所以上图两个卷积层可以认为是两个全连接层,唯一的作用就是在通道数上做一些混合,就如下图显示的:

NiN架构

  • 无全连接层

  • 交替使用NiN块和步幅为2的最大池化层,并逐步减少高宽和增大通道数

  • 最后使用全局平均池化层得到输出,使其输入通道数是类别数 

全局平均池化层:

窗口的高宽=输入的高宽

也就是对于每个通道,拿出最大的那个值 

VGG:VGG块 * 4 + 4096MLP * 2 + 输出数为1000的输出层

NiN:(NiN块 + MaxPooling)*3 + NiN块 + Global Mean Pooling

总结

  • NiN使用由一个卷积层和多个1×1卷积层组成的块。该块可以在卷积神经网络中使用,可以使每个像素都具有非线性。

  • NiN去除了容易造成过拟合的全连接层,将它们替换为全局平均汇聚层(即在所有位置上进行求和)。该汇聚层通道数量为所需的输出数量(例如,Fashion-MNIST的输出为10)。

  • 移除全连接层可减少过拟合,同时显著减少NiN的参数。

  • NiN的设计影响了许多后续卷积神经网络的设计。

 代码实现

NiN块

import torch
from torch import nn
from d2l import torch as d2l


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模型

net = nn.Sequential(
    # 因为数据集是灰度图,所以输入通道是1
    nin_block(1, 96, kernel_size=11, strides=4, padding=0),
    nn.MaxPool2d(3, stride=2),
    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
    nin_block(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    # 将四维的输出转成二维的输出,其形状为(批量大小,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)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值