1.GoogLeNet网络详解

网络中的创新点:
(1)引入了Inception结构(融合不同尺度的特征信息)
(2)使用1x1的卷积核进行降维以及映射处理 (虽然VGG网络中也有,但该论文介绍的更详细)
(3)添加两个辅助分类器帮助训练
(4)丢弃全连接层,使用平均池化层(大大减少模型参数,除去两个辅助分类器,网络大小只有vgg的1/20)

(1) Inception结构

inception的作用:增加网络深度和宽度的同时减少参数。

左图为原始结构,右图加上了降维功能。

在左图中,将特征矩阵同时输入到四个分支中进行处理(并行),将这四个分支处理后的特征矩阵按深度(channel维度)进行拼接,最后得到一个输出特征矩阵。

在右图中,通过增加三个1x1的卷积层达到降维的作用,目的是为了降维(减小深度),减少模型训练参数,减少计算量。

:每个分支所得特征矩阵的高和宽必须相同(通过调整stride和padding),以保证输出特征能在深度上进行拼接。

(2) 1x1卷积核降维


如果不使用1x1卷积核,使用64个5x5的卷积核进行卷积,就需要819200个参数;如果使用24个1x1的卷积核进行卷积,只需要50688个参数。

CNN参数个数 = 卷积核尺寸 × 卷积核深度 × 卷积核组数 = 卷积核尺寸 × 输入特征矩阵深度 × 输出特征矩阵深度

(3) 辅助分类器


在GoogLeNet网络中有两个辅助分类器,结构是完全一样的。这两个辅助分类器的输入分别来自Inception(4a)和Inception(4d)。

辅助分类器的第一层是一个平均池化下采样层,池化核大小为5x5,stride=3

第二层是卷积层,卷积核大小为1x1,stride=1,卷积核个数是128

第三层是全连接层,节点个数是1024

第四层是全连接层,节点个数是1000(对应分类的类别个数)

辅助分类器的两个分支的作用
(1)可以把它看做inception网络中的一个小细节,它确保了即便是隐藏单元和中间层也参与了特征计算,它们也能预测图片的类别,它在inception网络中起到一种调整的效果,并且能防止网络发生过拟合。

(2)给定深度相对较大的网络,有效传播梯度反向通过所有层的能力是一个问题。通过将辅助分类器添加到这些中间层,可以期望较低阶段分类器的判别力。在训练期间,它们的损失以折扣权重(辅助分类器损失的权重是0.3)加到网络的整个损失上。

GoogLeNet 网络参数

参数#1x1,#3x3reduce,#3x3,#5x5reduce,#5x5,#pool proj主要对应Inception结构的配置

#1x1对应着分支1上1x1的卷积核个数
#3x3reduce对应着分支2上1x1的卷积核个数
#3x3对应着分支2上3x3的卷积核个数
#5x5reduce对应着分支3上1x1的卷积核个数
#5x5对应着分支3上5x5的卷积核个数
pool proj对应着分支4上1x1的卷积核个数。

GoogLeNet 网络模型

2.使用Pytorch搭建GoogLeNet网络

model.py

定义卷积模板

在搭建网络之前先进行模板文件的创建,可以通过此方法定义卷积模板避免重复搭建conv和relu,卷积模板的定义:

class BasicConv2d(nn.Module):        #在搭建卷积层过程中通常将卷积和ReLU激活函数共同使用def __init__(self, in_channels, out_channels, **kwargs):super(BasicConv2d, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, **kwargs)self.relu = nn.ReLU(inplace=True)def forward(self, x):            #定义正向传播过程x = self.conv(x)x = self.relu(x)return x

定义Inception模板

class Inception(nn.Module):                 #定义Inception结构模板def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):  #结合googlenet网络参数和Inception结构super(Inception, self).__init__()self.branch1 = BasicConv2d(in_channels, ch1x1, kernel_size=1)    #分支1,使用定义的卷积模板,输入的特征矩阵深度为in_channels,卷积核个数为传入的ch1x1self.branch2 = nn.Sequential(BasicConv2d(in_channels, ch3x3red, kernel_size=1),           #分支2BasicConv2d(ch3x3red, ch3x3, kernel_size=3, padding=1)       #将padding设置为1,使输出特征矩阵和输入特征矩阵的高和宽保持一致,保证输出大小等于输入大小)self.branch3 = nn.Sequential(                                    #分支3BasicConv2d(in_channels, ch5x5red, kernel_size=1),BasicConv2d(ch5x5red, ch5x5, kernel_size=5, padding=2)       #保证输出大小等于输入大小:output_size=(input_size-5+2*2)/1+1=input_size)self.branch4 = nn.Sequential(                                    #分支4nn.MaxPool2d(kernel_size=3, stride=1, padding=1),BasicConv2d(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)

定义辅助分类器模板

class InceptionAux(nn.Module):                                    #定义辅助分类器def __init__(self, in_channels, num_classes):super(InceptionAux, self).__init__()self.averagePool = nn.AvgPool2d(kernel_size=5, stride=3)  #平均池化self.conv = BasicConv2d(in_channels, 128, kernel_size=1)  # output[batch, 128, 4, 4]self.fc1 = nn.Linear(2048, 1024)                          #输入节点个数128x4x4self.fc2 = nn.Linear(1024, num_classes)def forward(self, x):                                         #定义正向传播过程# aux1: N x 512 x 14 x 14, aux2: N x 528 x 14 x 14x = self.averagePool(x)# aux1: N x 512 x 4 x 4, aux2: N x 528 x 4 x 4x = self.conv(x)# N x 128 x 4 x 4x = torch.flatten(x, 1)x = F.dropout(x, 0.5, training=self.training)            #原论文采用0.7# N x 2048                                               #self.training会随着训练或测试的不同而变化x = F.relu(self.fc1(x), inplace=True)                    #当实例化一个模型model后,可以通过model.train()和model.eval()来控制模型的状态x = F.dropout(x, 0.5, training=self.training)            #在model.train()模式下self.training=True,在model.eval()模式下self.training=False# N x 1024x = self.fc2(x)# N x num_classesreturn x

定义GoogLeNet网络

class GoogLeNet(nn.Module):                                                      #定义GoogLeNetdef __init__(self, num_classes=1000, aux_logits=True, init_weights=False):   #初始化函数super(GoogLeNet, self).__init__()self.aux_logits = aux_logits                                             #将是否使用辅助分类器的布尔变量传入类变量中#根据GoogLeNet简图进行搭建self.conv1 = BasicConv2d(3, 64, kernel_size=7, stride=2, padding=3)      #为了将特征矩阵的高和宽缩减到原来的一半,这里将padding设置为3:(224-7+2*3)/2+1=112.5(pytorch默认向下取正)self.maxpool1 = nn.MaxPool2d(3, stride=2, ceil_mode=True)                #ceil_mode表示如果进行最大池化后得到的值为小数,设置为True就会向上取整,设置为False就会向下取整#省略LocalRespNorm,没什么用self.conv2 = BasicConv2d(64, 64, kernel_size=1)self.conv3 = BasicConv2d(64, 192, kernel_size=3, padding=1)self.maxpool2 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.inception3a = Inception(192, 64, 96, 128, 16, 32, 32)               #使用定义的Inception模板self.inception3b = Inception(256, 128, 128, 192, 32, 96, 64)self.maxpool3 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.inception4a = Inception(480, 192, 96, 208, 16, 48, 64)             #这里每一个Inception的输入都可以通过将上一层Inception层的四个分支的特征矩阵深度加起来得到self.inception4b = Inception(512, 160, 112, 224, 24, 64, 64)self.inception4c = Inception(512, 128, 128, 256, 24, 64, 64)self.inception4d = Inception(512, 112, 144, 288, 32, 64, 64)self.inception4e = Inception(528, 256, 160, 320, 32, 128, 128)self.maxpool4 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.inception5a = Inception(832, 256, 160, 320, 32, 128, 128)self.inception5b = Inception(832, 384, 192, 384, 48, 128, 128)if self.aux_logits:                                                    #如果使用辅助分类器,即aux_logits = True,则创建aux1和aux2self.aux1 = InceptionAux(512, num_classes)                         #输入是Inception4a的输出self.aux2 = InceptionAux(528, num_classes)                         #输入是Inception4b的输出self.avgpool = nn.AdaptiveAvgPool2d((1, 1))                            #nn.AdaptiveAvgPool2d()自适应平均池化下采样,参数(1,1)代表我们所需要的输出特征矩阵的高和宽self.dropout = nn.Dropout(0.4)                                         #不论输入特征矩阵的高和宽的大小,都可以通过自适应平均池化下采样得到所指定的输出特征矩阵的高和宽self.fc = nn.Linear(1024, num_classes)if init_weights:                                                       #如果init_weights = True,则对模型权重进行初始化self._initialize_weights()def forward(self, x):                                                      #定义正向传播过程# N x 3 x 224 x 224x = self.conv1(x)# N x 64 x 112 x 112x = self.maxpool1(x)# N x 64 x 56 x 56x = self.conv2(x)# N x 64 x 56 x 56x = self.conv3(x)# N x 192 x 56 x 56x = self.maxpool2(x)# N x 192 x 28 x 28x = self.inception3a(x)# N x 256 x 28 x 28x = self.inception3b(x)# N x 480 x 28 x 28x = self.maxpool3(x)# N x 480 x 14 x 14x = self.inception4a(x)# N x 512 x 14 x 14if self.training and self.aux_logits:    # eval model lose this layeraux1 = self.aux1(x)x = self.inception4b(x)# N x 512 x 14 x 14x = self.inception4c(x)# N x 512 x 14 x 14x = self.inception4d(x)# N x 528 x 14 x 14if self.training and self.aux_logits:    # eval model lose this layer   是否使用辅助分类器,在训练过程使用,测试过程不用aux2 = self.aux2(x)x = self.inception4e(x)# N x 832 x 14 x 14x = self.maxpool4(x)# N x 832 x 7 x 7x = self.inception5a(x)# N x 832 x 7 x 7x = self.inception5b(x)# N x 1024 x 7 x 7x = self.avgpool(x)# N x 1024 x 1 x 1x = torch.flatten(x, 1)# N x 1024x = self.dropout(x)x = self.fc(x)# N x 1000 (num_classes)if self.training and self.aux_logits:   # eval model lose this layer    是否使用辅助分类器,在训练过程使用,测试过程不用return x, aux2, aux1return xdef _initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')if m.bias is not None:nn.init.constant_(m.bias, 0)elif isinstance(m, nn.Linear):nn.init.normal_(m.weight, 0, 0.01)nn.init.constant_(m.bias, 0)

train.py

和VGG的train脚本基本一样,只有两点不同:

    net = GoogLeNet(num_classes=5, aux_logits=True, init_weights=True)    #5个类别,使用辅助分类器、权重初始化

GoogLeNet的网络输出 loss 有三个部分,分别是主干输出loss、两个辅助分类器输出loss(权重0.3)

logits, aux_logits2, aux_logits1 = net(images.to(device))   #三个输出:主输出、辅助分类器1的输出、辅助分类器2的输出
loss0 = loss_function(logits, labels.to(device))            #计算主分类器与真实标签之间的损失
loss1 = loss_function(aux_logits1, labels.to(device))       #计算辅助分类器1与真实标签之间的损失
loss2 = loss_function(aux_logits2, labels.to(device))       #计算辅助分类器2与真实标签之间的损失
loss = loss0 + loss1 * 0.3 + loss2 * 0.3                    #将三个损失相加,0.3是因为在原论文中按0.3的权重
loss.backward()                                             #将损失进行反向传播
optimizer.step()                                            #通过优化器更新模型参数

prdict.py

在预测过程不需要辅助分类器

    # create modelmodel = GoogLeNet(num_classes=5, aux_logits=False).to(device)     #将aux_logits=False就不会构建辅助分类器# load model weightsweights_path = "./googleNet.pth"assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)missing_keys, unexpected_keys = model.load_state_dict(torch.load(weights_path, map_location=device),strict=False)      #但是在保存模型时已经将辅助分类器的参数保存在权重当中,因此将strict=False#如果strict=True,就会精准匹配当前模型和需要载入的权重模型的结构

导师博客:https://blog.csdn.net/qq_37541097/article/details/103482003
导师github:https://github.com/WZMIAOMIAO/deep-learning-for-image-processing
模型参考:https://www.cnblogs.com/itmorn/p/11230388.html
代码用的导师的,自己又加了些备注,就放在自己的github里了:
https://github.com/Petrichor223/Deep_Learning/tree/master

GoogLeNet网络详解并使用pytorch搭建模型相关推荐

  1. ResNet网络详解并使用pytorch搭建模型、并基于迁移学习训练

    1.ResNet网络详解 网络中的创新点: (1)超深的网络结构(突破1000层) (2)提出residual模块 (3)使用Batch Normalization加速训练(丢弃dropout) (1 ...

  2. MobileNetv1、v2网络详解、使用pytorch搭建模型MobileNetv2并基于迁移学习训练

    1.MobileNetv1网络详解 传统卷积神经网络专注于移动端或者嵌入式设备中的轻量级CNN网络,相比于传统卷积神经网络,在准确率小幅降低的前提下大大减少模型参数与运算量.(相比VGG16准确率减少 ...

  3. VGG16网络详解并使用pytorch搭建模型

    VGG网络结构 网络中的亮点:通过堆叠多个3x3的卷积核来代替大尺度卷积核(减少所需参数),可以拥有相同的感受野 1.一张原始图片被resize到(224,224,3). 2.conv1两次[3,3] ...

  4. GoogleNet网络详解与keras实现

    GoogleNet网络详解与keras实现 GoogleNet网络详解与keras实现 GoogleNet系列网络的概览 Pascal_VOC数据集 第一层目录 第二层目录 第三层目录 Incepti ...

  5. GoogLeNet网络详解与模型搭建

    文章目录 1 模型介绍 2 GoogLeNet详解 Inception模块 辅助分类器 3 GoogLeNet网络结构 4 Pytorch模型搭建代码 1 模型介绍 GoogLeNet是2014年Ch ...

  6. 【深度神经网络】五、GoogLeNet网络详解

    概要 本篇文章的重点就是主要介绍GoogLeNet的网络架构,这个网络架构于2014年由Google团队提出.GoogLeNet的论文为:Going deeper with convolutions. ...

  7. GoogLenet网络详解

    GoogLenet VGG在2014年由牛津大学著名研究组vGG (Visual Geometry Group)提出,斩获该年lmageNet竞赛中Localization Task (定位任务)第一 ...

  8. 第十六章 ConvNeXt网络详解

    系列文章目录 第一章 AlexNet网络详解 第二章 VGG网络详解 第三章 GoogLeNet网络详解 第四章 ResNet网络详解 第五章 ResNeXt网络详解 第六章 MobileNetv1网 ...

  9. 【卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10)】

    卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10) 在上一章已经完成了卷积神经网络的结构分析,并通过各个模块理解 ...

最新文章

  1. libnet发包java语言_libnet-1.1.2.1
  2. Android 2D Graphics
  3. 【Nginx】应用静态化配置
  4. HAproxy - 铁钉 - 51CTO技术博客
  5. Sql Server系列:视图
  6. linux下mqm添加用户,Linux 下MQ的安装和配置亲测
  7. python处理word表格格式_python---word表格样式设置
  8. 害怕运维做到30岁还一事无成?你应该来这里看看
  9. 计算机网络(一)——一些概念
  10. pycharm安装scrapy失败_python爬虫框架scrapy
  11. QQ VS 360 大战开始
  12. 2022 CNCC 中国计算机大会参会总结
  13. 云计算技术与应用(高职组)赛题库 2019 年全国职业院校技能大赛题库
  14. Cadence软件license相关问题
  15. MySql数据的完整性
  16. WM_ERASEBKGND消息及位图背景与透明的实现
  17. [31期]上班这点事
  18. Android简单的编写一个txt阅读器(没有处理字符编码),适用于新手学习
  19. floating输入 高阻输入_按键怎么有那么多种接法,有的要电阻有的不用?实在搞糊涂了...
  20. VARIANT数据类型详解

热门文章

  1. Zookeeper系列(二)、核心原理
  2. 北斗授时装置(定时服务)京准为您来解读
  3. 第1关:使用C/C++语言编写PL/0编译程序的词法分析程序
  4. BZOJ4554 [Tjoi2016Heoi2016]游戏
  5. 五一山西游记之双林寺、乔家大院
  6. 量子比特大突破!原子薄材料成为“救世主”
  7. Vue案例:组件之间的传值问题
  8. 《征服 C 指针》摘录4:函数 与 指针
  9. 如何使用css样式将正方形图片显示为圆形图片布局
  10. 《剑指offer》每日三题