常见卷积神经网络结构

1. AlexNet

                                                                AlexNet网络结构

inputlayerkernelkernel_numstridepadoutputparameters
227*227*3CONV111*11*3964055*55*9611*11*3*96=35k
55*55*96MAX POOL13*32027*27*96
27*27*96NORM1
27*27*96CONV25*5*96256125*5*96*256=614k
27*27*256MAX POOL23*320
13*13*256NORM2
13*13*256CONV33*3*256113*3*256*384=885k
13*13*384CONV43*3*384113*3*384*384=1327k
13*13*384CONV53*3*384113*3*384*256=885k
13*13*256MAX POOL33*320
6*6*256FC640966*6*256*4096=3775W
4096FC740964096*4096=1678W
4096FC810004096*4096=410W

输入一个227*227*3的图像,(长和宽为227个像素的三通道彩色图),第一层卷积的卷积核大小为11*11*3,并且由96个卷积核组成。所有卷积核均以stride为4滑过整张227*227*3的图片,然后由卷积输出层分辨率计算公式不难得出输出大小为55*55*96.

1.1 特点:

  1. 使用Relu作为激活函数
  2. 使用多种方法避免过拟合

使用Relu作为激活函数:

为了加快深度神经网络的训练速度,将神经网络神经元激活函数f(x) = tanh(x) 或f(x) = (1+e^{-x})-1 改为f(x) = max(0;x) 即ReLUs.

使用多种方法避免过拟合:

AlexNet有超过6000万的参数,虽然ILSVRC比赛含有大量的训练数据,但仍然很难完成对如此庞大参数的完全训练,从而导致严重的过拟合问题。AlexNet很巧妙地运用下面两种方法处理了这个问题:

(1) 数据增强:在图像领域,最简单也最常用的避免过拟合的方法就是对数据集的增强。

  • 对原始图片做随机裁剪。假如原始输入图片的大小为256*256,那么训练时可随机从256*256的图片上裁剪224*224的图片作为网络的输入。
  • 另外还有一些常见数据增强方法,AlexNet论文中并没有全部用到,例如训练时对原始图片进行随机地上下、左右翻转,平移,缩放,旋转等。

(2) 使用dropout:该方法一方面是为了避免过拟合,另一方面是使用更有效的方式进行模型融合。具体方法是在训练时让神经网络中每一个中间层神经元以5的一定倍数的概率(如0.5)置为0.当某个神经元被置0时,它便不会参与前向传播以及反向回传的计算。因此每当有一个新的图片输入时就意味着网络随机采样出一个新的网络结构,而真值的整个网络的权重一致是共享的。

 2. GoogLeNet

GoogLeNet最初的想法很简单,就是若想要更好的预测效果,就要增加网络的复杂度,即从两个角度出发:网络深度和网络宽度。但是这个思路有两个较为明显的问题。

  • 更复杂的网络意味着更多的参数,所以很容易过拟合
  • 更复杂的网络会带来更大的计算资源的消耗,并且会导致计算资源的浪费。

GoogLeNet引用了inception结构来解决这个问题:这个结构是将256个均匀分布在3*3尺度的特征转换成多个不同尺度的聚类,如96个1*1、96个3*3和64个5*5分别聚在一起,这样可以使计算更有效,收敛更快。

除了inception结构,GoogLeNet的另一个特点是主干网络部分全部使用卷积网络,仅仅在最终分类部分使用全连接层

 

 

代码实现:

class InceptionA(torch.nn.Module):
    def __init__(self, in_channels):
        super(InceptionA, self).__init__()
        # 第一层
        self.branch1x1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
        # 第二层
        self.branch5x5_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
        self.branch5x5_2 = torch.nn.Conv2d(16, 24, kernel_size=5, padding=2)
        # 第三层
        self.branch3x3_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
        self.branch3x3_2 = torch.nn.Conv2d(16, 24, kernel_size=3, padding=1)
        self.branch3x3_3 = torch.nn.Conv2d(24, 24, kernel_size=3, padding=1)
        # 第四层
        self.branch_pool = torch.nn.Conv2d(in_channels, 24, kernel_size=1)

    def forward(self, x):
        branch1x1 = self.branch1x1(x)

        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)

        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        branch3x3 = self.branch3x3_3(branch3x3)

        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
        branch_pool = self.branch_pool(branch_pool)
        outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
        return torch.cat(outputs, dim=1)


class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(88, 20, kernel_size=5)

        self.incep1 = InceptionA(in_channels=10)
        self.incep2 = InceptionA(in_channels=20)

        self.mp = torch.nn.MaxPool2d(2)
        # 1408的值可以通过先实例化一个对象 然后输出
        self.fc = torch.nn.Linear(1408, 10)

    def forward(self, x):
        # 获取x的第0列大小 也就是batch的大小
        in_size = x.size(0)
        x = F.relu(self.mp(self.conv1(x)))
        x = self.incep1(x)
        x = F.relu(self.mp(self.conv2(x)))
        # 执行完后已经变为(batch, 88, 4, 4)
        x = self.incep2(x)
        # print(x.shape)
        # 压缩x为 in_size行 自适应列 即(batch, 88*4*4)
        # 此句的目的就是把除了batch以外的c、w、h压缩在一起
        x = x.view(in_size, -1)
        x = self.fc(x)
        return x


model = Net()

 3. ResNet

是不是网络结构越深、卷积层数量堆叠越多越好呢?看下图,自然不是,56层的卷积神经网络在训练和测试方面的误差都大于20层的网络,可以排除过拟合的干扰因素,真实的原因是“梯度消失

如公式(1)所示,网络的损失函数为F(X,W),其反向传播的梯度值如公式(2).同样的原理,扩展到多层神经网络,网络的损失函数如公式(3)表示,其中n为神经网络的层数,最终根据链式法则可推出第i层的梯度如公式(4)所示。因此可以看出,随着误差的回传,前层网络的梯度也变得越来越小。

                   Loss = F(X,W)                                                                         (公式1)

                  \frac{\partial Loss}{\partial X} = \frac{\partial F(X,W)}{\partial X}                                                                    (公式2)

                                                                                     Loss = F_n(X_n,W_n), L_n=F_{n-1}(X_{n-1},W_{n-1})...L_2=F_1(X_1,W_1)           (公式3)                    

          \frac{\partial Loss}{\partial X_i} = \frac{\partial F_n(X_n,W_n)}{\partial X_n}* \cdots *\frac{\partial F(X_{i+1},W_{i+1})}{X_{i+1}}                               (公式4) 

 为了解决神经网络过深导致的梯度消失问题,ResNet巧妙地引入了残差结构,如下图所示:

即将输出层H(X)=F(X)改为 H(X)=F(X)+X,也就是从公式4变为了公式5.所以梯度就不会消失了

\frac{\partial X_{i+1}}{\partial X_i} = \frac{\partial X_i+\partial F(X_i,W_i)}{\partial X_i} = 1 + \frac{\partial F(X_i,W_i)}{\partial X_i}                                     (公式5) 

除了残差结构外,ResNet还用了堆叠式残差结构,每个残差模块又由多个小尺度kernel组成,整个ResNet除了最后用于分类的全连接层以外都是全卷积的。

4. VGGNet

VGGNet包含两种结构,分别为16层和19层。从上图可以看出VGG的所有卷积层的kernel都是3*3.VGGNet中连续使用3组3*3kernel的原因是它与使用1个7*7kernel产生的效果相同。该操作带来的一个好处是参数数量的减少,因为对于一个包含了C个kernel的卷积层来说,原来的参数个数为7*7*C,而新的参数个数为3*(3*3*C) 

 5. Wide ResNet

设计了更宽的残差模块,实验证明50层的加宽残差网络效果比152层的原ResNet网络效果更好

6.  ResNeXT

 ResNeXT在ResNet的基础上通过加宽inception个数的方式来扩展残差模块,如下图

 7. DenseNet

网络模块如下图所示,在DenseNet中,每一层都与其他层相关联,这样的设计也大大缓解了梯度消失问题。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值