Backbone 之 Inception:纵横交错 (Pytorch实现及代码解析)

 背景:

一般来说,增加网络的深度和宽度可以提升网络的性能,但是这样做也会带来参数量的大幅度增加,同时较深的网络需要较多的数据,否则很容易产生过拟合现象。除此之外,增加深度的有一个坏处就是很容易造成梯度消失的现象。由此,ImageNet大赛上,GoogLeNet(Inception)很好地解决了这个问题。

Inception基础结构图:

Backbone 之 Inception:纵横交错 (Pytorch实现及代码解析)_第1张图片

Inception特点:

  • 采用并行结构代替之前VGG的深度串行结构

  • 采用几个大小不同的卷积运算和池化,最后再拼接(通道拼接)到一起

  • 1x1、3x3、5x5的卷积运算对应不同的特征图区域,这样做的好处:可以得到更好的图像表征信息

  • 精心设计了22层卷积网络

  • Inception的参数量较少,适合处理大规模数据,尤其是对于计算资源有限的平台

为进一步降低参数量,Inception又增加了较多的1x1卷积块进行降维,改进为Inception v1版本,Inception v1共9个上述堆叠的模块,共有22层,在最后的Inception 模块中还是用了全局平均池化。同时为避免造成网络训练时带来的梯度消失的现象,在这里引入两个辅助的分类器,在第三个和第六个的Inception模块输出后执行Softmax并计算损失,在训练时和最后的损失一并回传。


Inception v1基础结构图:

Backbone 之 Inception:纵横交错 (Pytorch实现及代码解析)_第2张图片

Inception v1代码:

import torch
from torch import nn
import torch.nn.functional as F
###定义一个包含卷积和ReLU池化的基础卷积块
class BasicConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, padding=0):
        super(BasicConv2d, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, padding=padding)
    def forward(self, x):
        x = self.conv(x)
        return F.relu(x, inplace=True)
###Inceptionv1 类,初始时需要提供各个子模块的通道数大小
class Inceptionv1(nn.Module):
     def __init__(self, in_dim, hid_1_1, hid_2_1, hid_2_3, hid_3_1, out_3_5, out_4_1):
          super(Inceptionv1, self).__init__()
          ###四个子模块各自的网络定义
          self.branch1x1 = BasicConv2d(in_dim, hid_1_1, 1)
          self.branch3x3 = nn.Sequential(
               BasicConv2d(in_dim, hid_2_1, 1),
               BasicConv2d(hid_2_1, hid_2_3, 3, padding=1)
          )
          self.branch5x5 = nn.Sequential(
               BasicConv2d(in_dim, hid_3_1, 1),
               BasicConv2d(hid_3_1, out_3_5, 5, padding=2)
          )
          self.branch_pool = nn.Sequential(
               nn.MaxPool2d(3, stride=1, padding=1),
               BasicConv2d(in_dim, out_4_1, 1)
          )
###定义前向传播
     def forward(self, x):
          b1 = self.branch1x1(x)
          b2 = self.branch3x3(x)
          b3 = self.branch5x5(x)
          b4 = self.branch_pool(x)
          ###将这四个子模块沿着通道方向进行拼接
          output = torch.cat((b1, b2, b3, b4), dim=1)
          return output
​
​

Inception v2特点:

  • 增加BN层

  • 利用两个3*3来代替5x5卷积,减小了参数量,也提升网络的非线性能力

Inception v2结构示意图:

Backbone 之 Inception:纵横交错 (Pytorch实现及代码解析)_第3张图片

代码如下:

import torch
from torch import nn
import torch.nn.functional as F
​
class BasicConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, padding=0):
        super(BasicConv2d, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, padding=padding)
        self.bn = nn.BatchNorm2d(out_channels, eps=0.001)
    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        return F.relu(x, inplace=True)
​
class Inceptionv2(nn.Module):
    def __init__(self):
        super(Inceptionv2, self).__init__()
        self.branch1 = BasicConv2d(192, 96, 1, 0)
        self.branch2 = nn.Sequential(
            BasicConv2d(192, 48, 1, 0),
            BasicConv2d(48, 64, 3, 1)
        )
        self.branch3 = nn.Sequential(
            BasicConv2d(192, 64, 1, 0),
            BasicConv2d(64, 96, 3, 1),
            BasicConv2d(96, 96, 3, 1)
        )
        self.branch4 = nn.Sequential(
            nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
            BasicConv2d(192, 64, 1, 0)
        )
    def forward(self, x):
        x0 = self.branch1(x)
        x1 = self.branch2(x)
        x2 = self.branch3(x)
        x3 = self.branch4(x)
        out = torch.cat((x0, x1, x2, x3), 1)
        return out
​
​

Backbone 之 Inception:纵横交错 (Pytorch实现及代码解析)_第4张图片

你可能感兴趣的:(深度学习算法,目标检测,python,机器学习,pytorch,神经网络,深度学习)