基于 Pytorch 解读 GoogLeNet 现代卷积神经网络

Python中文社区

共 9396字,需浏览 19分钟

 · 2021-08-25

1 概述

GoogLeNet关键点:

保证算力情况下增大宽度和深度
宽度:利用Inception结构同时执行多个网络结构
深度:利用辅助分类器防止梯度消失
多尺度训练和预测
适用于多种计算机视觉任务

多尺度训练对全卷积网络有效,一般设置几种不同尺度的图片,训练时每隔一定iterations随机选取一种尺度训练。这样训练出来的模型鲁棒性强,其可以接受任意大小的图片作为输入,使用尺度小的图片测试速度会快些,但准确度低,用尺度大的图片测试速度慢,但是准确度高。

例如:训练的时候,把图片缩放到不同大小输入给同一个网络,网络就能看到不一样大小范围的内容,然后就叫做多尺度训练;好处是可以适应不同尺度的输入,泛化性好。把一个特征层用由不同感受野的卷积核组成的网络层(例如SPP)处理,这层网络的同一个像素位置就能看到不同范围的上层特征,就叫做多尺度特征融合;好处是能考虑到不同范围的空间特征上下文(例如头发下面一般会有一张脸)。把一个网络中不同深度的层做融合:浅层感受野小,分辨率大,能够处理并保存小尺度的几何特征;高层感受野大,分辨率小,能够处理并保存大尺度的语义特征。这也叫做多尺度特征融合;好处是能够将语义特征和几何特征进行融合(例如这块区域是头发,低分辨率图上的分界线一般是线状特征和非线状特征的边界)。
下面根据论文的顺序介绍该模型:

1、比赛成绩:

ILSVRC14分类任务第一(classification)、检测任务第一(detection)。GoogLeNet和VGGNet同时期,根据VGGNet的论文,单模型VGGNet更好,但七个模型集成之后GoogLeNet更好

2、背景介绍:

GoogLeNet是一个基于Hebbian法则和多尺度处理构建的网络结构,共有22层,相较于当时两年前的AlexNet参数少了12倍,但精确率提高了很多;不仅能用于分类任务,还可以用于检测任务。

在目标检测领域中,最大的提升并不是来自于使用更大更深的网络,而是将传统CV方法和更深的网络结构结合在一起,比如R-CNN:先利用低层语义信息找到bbox,再用CNN进行分类。

由于移动设备和嵌入式计算的发展,算法的效率即精确率和内存占用变得很重要,GoogLeNet考虑到了这一点,并权衡了这两者的关系。一个好的模型应当不仅有学术性,而且还能应用于真实世界中。

Inception结构的想法来源:

之前的研究中有人利用多个不同尺寸的Gabor滤波器处理多尺度问题(其实这个想法是来源于灵长类动物的视觉皮质的神经科学模型),但模型层数太少,而GoogLeNet将Inception重复很多次以此实现22层的网络结构
1 x 1卷积的想法来源于NiN

3、动机和高层次的考虑:

将网络设计得更宽、更深的问题:

容易过拟合
计算资源有限且越大的网络利用率未必高(如参数很多0)
为了解决这两个问题,需要将FC层或卷积层转换成稀疏连接的结构(这一点除了是模仿生物以外,有坚实的理论基础),但使用稀疏连接的结构会导致硬件效率变低(更均匀的网络结构、卷积核和更大的batch size才能使计算效率更高),可以将稀疏矩阵合并成相对稠密的子矩阵,以此解决稀疏矩阵相乘的问题。

2 版本

GoogLeNet Incepetion V1
GoogLeNet Inception V2
GoogLeNet凭借其优秀的表现,得到了很多研究人员的学习和使用,因此Google团队又对其进行了进一步发掘改进,产生了升级版本的GoogLeNet。这一节介绍的版本记为V2,文章为:《Rethinking the Inception Architecture for Computer Vision》。
用nx1卷积来代替大卷积核,这里设定n=7来应对17x17大小的feature map。该结构被正式用在GoogLeNet V2中。

3 含并行连结的网络(GoogLeNet)

3.1 Inception块

在GoogLeNet中,基本的卷积块被称为Inception块(Inception block)。这很可能得名于电影《盗梦空间》(Inception),因为电影中的一句话“我们需要走得更深”(“We need to go deeper”)。

在这里插入图片描述

Inception块由四条并行路径组成。
前三条路径使用窗口大小为 的卷积层,从不同空间大小中提取信息。
中间的两条路径在输入上执行 卷积,以减少通道数,从而降低模型的复杂性。
第四条路径使用 最大汇聚层,然后使用 卷积层来改变通道数。
这四条路径都使用合适的填充来使输入与输出的高和宽一致,最后我们将每条线路的输出在通道维度上连结,并构成Inception块的输出。在Inception块中,通常调整的超参数是每层输出通道的数量。

import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l


class Inception(nn.Module):
    # `c1`--`c4` 是每条路径的输出通道数
    def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):
        super(Inception, self).__init__(**kwargs)
        # 线路1,单1 x 1卷积层
        self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)
        # 线路2,1 x 1卷积层后接3 x 3卷积层
        self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)
        self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        # 线路3,1 x 1卷积层后接5 x 5卷积层
        self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)
        self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        # 线路4,3 x 3最大汇聚层后接1 x 1卷积层
        self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.p4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)

    def forward(self, x):
        p1 = F.relu(self.p1_1(x))
        p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))
        p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))
        p4 = F.relu(self.p4_2(self.p4_1(x)))
        # 在通道维度上连结输出
        return torch.cat((p1, p2, p3, p4), dim=1)

那么为什么GoogLeNet这个网络如此有效呢?首先我们考虑一下滤波器(filter)的组合,它们可以用各种滤波器尺寸探索图像,这意味着不同大小的滤波器可以有效地识别不同范围的图像细节。同时,我们可以为不同的滤波器分配不同数量的参数

3.2 结构

GoogLeNet 一共使用 9 个Inception块和全局平均汇聚层的堆叠来生成其估计值。Inception块之间的最大汇聚层可降低维度。
第一个模块类似于 AlexNet 和 LeNet,Inception块的栈从VGG继承,全局平均汇聚层避免了在最后使用全连接层。


现在,我们逐一实现GoogLeNet的每个模块。第一个模块使用 64 个通道、 卷积层。
b1 = nn.Sequential(nn.Conv2d(164, kernel_size=7, stride=2, padding=3),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

第二个模块使用两个卷积层:第一个卷积层是 64个通道、 卷积层;第二个卷积层使用将通道数量增加三倍的 卷积层。
这对应于 Inception 块中的第二条路径。

b2 = nn.Sequential(nn.Conv2d(6464, kernel_size=1),
                   nn.ReLU(),
                   nn.Conv2d(64192, kernel_size=3, padding=1),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

第三个模块串联两个完整的Inception块。
第一个 Inception 块的输出通道数为 ,四个路径之间的输出通道数量比为
第二个和第三个路径首先将输入通道的数量分别减少到 ,然后连接第二个卷积层。第二个 Inception 块的输出通道数增加到 ,四个路径之间的输出通道数量比为
第二条和第三条路径首先将输入通道的数量分别减少到

b3 = nn.Sequential(Inception(19264, (96128), (1632), 32),
                   Inception(256128, (128192), (3296), 64),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

第四模块更加复杂,
它串联了5个Inception块,其输出通道数分别是
这些路径的通道数分配和第三模块中的类似,首先是含 卷积层的第二条路径输出最多通道,其次是仅含 卷积层的第一条路径,之后是含 卷积层的第三条路径和含 最大汇聚层的第四条路径。
其中第二、第三条路径都会先按比例减小通道数。
这些比例在各个 Inception 块中都略有不同。

b4 = nn.Sequential(Inception(480192, (96208), (1648), 64),
                   Inception(512160, (112224), (2464), 64),
                   Inception(512128, (128256), (2464), 64),
                   Inception(512112, (144288), (3264), 64),
                   Inception(528256, (160320), (32128), 128),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

第五模块包含输出通道数为 的两个Inception块。
其中每条路径通道数的分配思路和第三、第四模块中的一致,只是在具体数值上有所不同。
需要注意的是,第五模块的后面紧跟输出层,该模块同 NiN 一样使用全局平均汇聚层,将每个通道的高和宽变成1。
最后我们将输出变成二维数组,再接上一个输出个数为标签类别数的全连接层。

b5 = nn.Sequential(Inception(832256, (160320), (32128), 128),
                   Inception(832384, (192384), (48128), 128),
                   nn.AdaptiveAvgPool2d((1,1)),
                   nn.Flatten())

net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(102410))
X = torch.rand(size=(119696))
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape:\t', X.shape)

nn.AdaptiveAvgPool2d((1,1)),也做个一个降维度哦!

4 训练

使用 Fashion-MNIST 数据集来训练我们的模型。在训练之前,我们将图片转换为 $96 \times 96$ 分辨率。
lr, num_epochs, batch_size = 0.110128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

5 总结

  • Inception 块相当于一个有4条路径的子网络。它通过不同窗口形状的卷积层和最大汇聚层来并行抽取信息,并使用 卷积层减少每像素级别上的通道维数从而降低模型复杂度。

  • GoogLeNet将多个设计精细的Inception块与其他层(卷积层、全连接层)串联起来。其中Inception块的通道数分配之比是在 ImageNet 数据集上通过大量的实验得来的。

参考

[1].https://zh-v2.d2l.ai/index.html

作者简介:李响Superb,CSDN百万访问量博主,普普通通男大学生,深度学习算法、医学图像处理专攻,偶尔也搞全栈开发,没事就写文章,you feel me?
博客地址:
lixiang.blog.csdn.net



点击下方阅读原文加入社区会员

浏览 45
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报