GoogleNet

GoogleNet

目录

GoogleNet

简介

结构

核心思想

1.1x1的卷积

2.多个尺寸上进行卷积再聚合

3.GAP代替全连接层

4.辅助分支分类器

简介

inception(也称GoogLeNet)是2014年Christian Szegedy提出的一种全新的深度学习结构,在这之前的AlexNet、VGG等结构都是通过增大网络的深度(层数)来获得更好的训练效果,但层数的增加会带来很多负作用,比如overfit、梯度消失、梯度爆炸等。inception的提出则从另一种角度来提升训练结果:能更高效的利用计算资源,在相同的计算量下能提取到更多的特征,从而提升训练结果。(多个尺寸上进行卷积再聚合,把相关性强的特征聚集到一起)

结构

inception模块的基本结构如下图,整个inception结构就是由多个这样的inception模块串联起来的。inception结构的主要贡献有两个:一是使用1x1的卷积来进行升降维;二是在多个尺寸上同时进行卷积再聚合。

核心思想

1.1x1的卷积

  • 作用1:在相同尺寸的感受野中叠加更多的卷积,能提取到更丰富的特征。

    这个观点来自于Network in Network(NIN, https://arxiv.org/pdf/1312.4400.pdf),结构里三个1x1卷积都起到了该作用。

     

左侧是是传统的卷积层结构(线性卷积),在一个尺度上只有一次卷积;右图是Network in Network结构(NIN结构),先进行一次普通的卷积(比如3x3),紧跟再进行一次1x1的卷积,对于某个像素点来说1x1卷积等效于该像素点在所有特征上进行一次全连接的计算,所以右侧图的1x1卷积画成了全连接层的形式,需要注意的是NIN结构中无论是第一个3x3卷积还是新增的1x1卷积,后面都紧跟着激活函数(比如relu)。将两个卷积串联,就能组合出更多的非线性特征。

总结:NIN的结构和传统的神经网络中多层的结构有些类似,后者的多层是跨越了不同尺寸的感受野(通过层与层中间加pool层),从而在更高尺度上提取出特征;NIN结构是在同一个尺度上的多层(中间没有pool层),从而在相同的感受野范围能提取更强的非线性。

  • 作用2:使用1x1卷积进行降维,降低了计算复杂度。

    结构里3x3卷积和5x5卷积前的1x1卷积都起到了这个作用。当某个卷积层输入的特征数较多,对这个输入进行卷积运算将产生巨大的计算量;如果对输入先进行降维,减少特征数后再做卷积计算量就会显著减少。

    下图是优化前后两种方案的乘法次数比较,同样是输入一组有192个特征、32x32大小,输出256组特征的数据,第一张图直接用3x3卷积实现,需要192x256x3x3x32x32=452984832次乘法;第二张图先用1x1的卷积降到96个特征,再用3x3卷积恢复出256组特征,需要192x96x1x1x32x32+96x256x3x3x32x32=245366784次乘法,使用1x1卷积降维的方法节省了一半的计算量。

    疑问:用1x1卷积降到96个特征后特征数不就减少了么,会影响最后训练的效果么?答案是否定的,只要最后输出的特征数不变(256组),中间的降维类似于压缩的效果,并不影响最终训练的结果。其只是改变了一像素点的特征数,并未改变相邻像素之间的关系。

2.多个尺寸上进行卷积再聚合

从结构图可以看到对输入做了4个分支,分别用不同尺寸的filter进行卷积或池化,最后再在特征维度上拼接到一起。这种全新的结构有什么好处呢?Szegedy从多个角度进行了解释:

  • 解释1:在直观感觉上在多个尺度上同时进行卷积,能提取到不同尺度的特征。特征更为丰富也意味着最后分类判断时更加准确。

  • 解释2:利用稀疏矩阵分解成密集矩阵计算的原理来加快收敛速度。

举个例子下图左侧是个稀疏矩阵(很多元素都为0,不均匀分布在矩阵中),和一个2x2的矩阵进行卷积,需要对稀疏矩阵中的每一个元素进行计算;如果像右图那样把稀疏矩阵分解成2个子密集矩阵,再和2x2矩阵进行卷积,稀疏矩阵中0较多的区域就可以不用计算,计算量就大大降低。

这个原理应用到inception上就是要在特征维度上进行分解!

传统的卷积层的输入数据只和一种尺度(比如3x3)的卷积核进行卷积,输出固定维度(比如256个特征)的数据,所有256个输出特征基本上是均匀分布在3x3尺度范围上,这可以理解成输出了一个稀疏分布的特征集;而inception模块在多个尺度上提取特征(比如1x1,3x3,5x5),输出的256个特征就不再是均匀分布,而是相关性强的特征聚集在一起(比如1x1的的96个特征聚集在一起,3x3的96个特征聚集在一起,5x5的64个特征聚集在一起),这可以理解成多个密集分布的子特征集。这样的特征集中因为相关性较强的特征聚集在了一起,不相关的非关键特征就被弱化,同样是输出256个特征,inception方法输出的特征“冗余”的信息较少。

用这样的“纯”的特征集层层传递最后作为反向计算的输入,自然收敛的速度更快。

解释3:Hebbin赫布原理。

Hebbin原理是神经科学上的一个理论,解释了在学习的过程中脑中的神经元所发生的变化,用一句话概括就是fire togethter, wire together。赫布认为“两个神经元或者神经元系统,如果总是同时兴奋,就会形成一种‘组合’,其中一个神经元的兴奋会促进另一个的兴奋”。比如狗看到肉会流口水,反复刺激后,脑中识别肉的神经元会和掌管唾液分泌的神经元会相互促进,“缠绕”在一起,以后再看到肉就会更快流出口水。用在inception结构中就是要把相关性强的特征汇聚到一起。这有点类似上面的解释2,把1x1,3x3,5x5的特征分开。因为训练收敛的最终目的就是要提取出独立的特征,所以预先把相关性强的特征汇聚,就能起到加速收敛的作用。

在inception模块中有一个分支使用了max pooling,作者认为pooling也能起到提取特征的作用,所以也加入模块中。注意这个pooling的stride=1,pooling后没有减少数据的尺寸。

总结:稀疏连接有两种方法,一种是空间(spatial)上的稀疏连接,也就是传统的CNN卷积结构:只对输入图像的某一部分patch进行卷积,而不是对整个图像进行卷积,共享参数降低了总参数的数目减少了计算量;另一种方法是在特征(feature)维度进行稀疏连接,就是前一节提到的在多个尺寸上进行卷积再聚合,把相关性强的特征聚集到一起,每一种尺寸的卷积只输出256个特征中的一部分,这也是种稀疏连接。

3.GAP代替全连接层

Network in Network(NIN, https://arxiv.org/pdf/1312.4400.pdf)最早提出了用Global Average Pooling(GAP)层来代替全连接层的方法,具体方法就是对每一个feature上的所有点做平均,有n个feature就输出n个平均值作为最后的softmax的输入。

好处:1、对数据在整个feature上作正则化,防止了过拟合;2、不再需要全连接层,减少了整个结构参数的数目(一般全连接层是整个结构中参数最多的层),过拟合的可能性降低;3、不用再关注输入图像的尺寸,因为不管是怎样的输入都是一样的平均方法,传统的全连接层要根据尺寸来选择参数数目,不具有通用性。

4.辅助分支分类器

inception结构在在某些层级上加了分支分类器,输出的loss乘以个系数再加到总的loss上,这里的分支分类器只是在训练时使用,在正常预测时会被去掉。辅助分支分类器促进了更稳定的学习和更好的收敛,往往在接近训练结束时,辅助分支网络开始超越没有任何分支的网络的准确性,达到了更高的水平。

作者认为可以防止梯度消失问题(事实上在较低的层级上这样处理基本没作用,作者在后来的inception v3论文中做了澄清)。

补充:整体网络结构

### GoogleNet 模型介绍、架构及应用 GoogleNet,也被称为 Inception-v1,是由 Google 团队在 2014 年提出的一种深度卷积神经网络架构,主要用于图像分类和特征提取任务。该模型在 ILSVRC(ImageNet Large Scale Visual Recognition Challenge)比赛中表现出色,取得了优异成绩,其核心创新在于引入了“Inception”模块,这一模块的设计显著提高了模型的性能,同时控制了计算成本。 #### Inception 模块 Inception 模块是 GoogleNet 的核心组成部分,其设计目的是在不显著增加计算复杂度的前提下,提高模型的深度和宽度。Inception 模块通过并行使用不同大小的卷积核(如 1x1、3x3、5x5)以及池化操作来提取不同尺度的特征,并通过 1x1 卷积核来降低特征图的维度,从而减少计算量[^1]。这种多尺度特征提取机制使得模型能够在不同感受野上捕获图像信息,提高了分类的准确性。 #### 架构概述 GoogleNet 的整体架构由多个 Inception 模块堆叠而成,模块之间通过卷积层和池化层进行连接。整个网络的深度达到了 22 层(计算池化层),并且在网络的不同层次中使用了不同大小的卷积核以提取多层次的特征[^2]。此外,GoogleNet 还引入了两个辅助分类器,用于在网络的中间层进行分类预测,以缓解梯度消失问题并提高模型的收敛速度。 以下是一个简化的 GoogleNet 架构示意图: ```python # 简化的 GoogleNet 架构示例 class InceptionModule(nn.Module): def __init__(self, in_channels, out_channels_1x1, out_channels_3x3_reduce, out_channels_3x3, out_channels_5x5_reduce, out_channels_5x5, pool_proj): super(InceptionModule, self).__init__() self.branch1 = nn.Conv2d(in_channels, out_channels_1x1, kernel_size=1) self.branch2 = nn.Sequential( nn.Conv2d(in_channels, out_channels_3x3_reduce, kernel_size=1), nn.Conv2d(out_channels_3x3_reduce, out_channels_3x3, kernel_size=3, padding=1) ) self.branch3 = nn.Sequential( nn.Conv2d(in_channels, out_channels_5x5_reduce, kernel_size=1), nn.Conv2d(out_channels_5x5_reduce, out_channels_5x5, kernel_size=5, padding=2) ) self.branch4 = nn.Sequential( nn.MaxPool2d(kernel_size=3, stride=1, padding=1), nn.Conv2d(in_channels, pool_proj, kernel_size=1) ) def forward(self, x): branch1 = self.branch1(x) branch2 = self.branch2(x) branch3 = self.branch3(x) branch4 = self.branch4(x) return torch.cat([branch1, branch2, branch3, branch4], dim=1) class GoogleNet(nn.Module): def __init__(self, num_classes=1000): super(GoogleNet, self).__init__() self.features = nn.Sequential( nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3), nn.MaxPool2d(kernel_size=3, stride=2, padding=1), nn.Conv2d(64, 64, kernel_size=1), nn.Conv2d(64, 192, kernel_size=3, padding=1), nn.MaxPool2d(kernel_size=3, stride=2, padding=1), InceptionModule(192, 64, 96, 128, 16, 32, 32), InceptionModule(256, 128, 128, 192, 32, 96, 64), nn.MaxPool2d(kernel_size=3, stride=2, padding=1), InceptionModule(480, 192, 96, 208, 16, 48, 64), InceptionModule(512, 160, 112, 224, 24, 64, 64), InceptionModule(512, 128, 128, 256, 24, 64, 64), InceptionModule(512, 112, 144, 288, 32, 64, 64), InceptionModule(528, 256, 160, 320, 32, 128, 128), nn.MaxPool2d(kernel_size=3, stride=2, padding=1), InceptionModule(832, 256, 160, 320, 32, 128, 128), InceptionModule(832, 384, 192, 384, 48, 128, 128), nn.AdaptiveAvgPool2d((1, 1)), nn.Dropout(0.4), nn.Conv2d(1024, num_classes, kernel_size=1) ) def forward(self, x): x = self.features(x) x = x.view(x.size(0), -1) return x ``` #### 应用 GoogleNet 被广泛应用于图像分类、目标检测、图像分割等计算机视觉任务。由于其高效的计算设计和优异的性能,GoogleNet 成为了许多后续深度学习模型的基础架构。此外,GoogleNet 还被用于迁移学习,通过微调预训练模型,可以在小规模数据集上取得良好的效果。在实际应用中,GoogleNet 可以通过开源框架如 TensorFlow 和 PyTorch 进行快速实现和部署[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值