常见的卷积神经网络AlexNet

1.论文解读

第一个典型的CNN是LeNet5网络结构,但是第一个引起大家注意的网络却是AlexNet,也就是文章《ImageNet Classification with Deep Convolutional Neural Networks》介绍的网络结构。这篇文章的网络是在2012年的ImageNet竞赛中取得冠军的一个模型整理后发表的文章。作者是多伦多大学的Alex Krizhevsky等人。Alex Krizhevsky其实是Hinton的学生,这个团队领导者是Hinton,那么Hinton是谁呢?这就要好好说说了,网上流行说 Hinton, LeCun和Bengio是神经网络领域三巨头,LeCun就是LeNet5作者(Yann LeCun),昨天的文章就提到了这个人。而今天的主角虽然不是Hinton,但却和他有关系,这篇的论文第一作者是Alex,所以网络结构称为AlexNet。这篇论文很有意思,因为我读完这篇论文之后,没有遇到比较难以理解的地方,遇到的都是之前学过的概念,比如Relu,dropout。之前学的时候只知道Relu是怎么一回事,今天才知道它真正的来源。这篇文章在2012年发表,文章中的模型参加的竞赛是ImageNet LSVRC-2010,该ImageNet数据集有1.2 million幅高分辨率图像,总共有1000个类别。测试集分为top-1和top-5,并且分别拿到了37.5%和17%的error rates。这样的结果在当时已经超过了之前的工艺水平。AlexNet网络结构在整体上类似于LeNet,都是先卷积然后在全连接。但在细节上有很大不同。AlexNet更为复杂。AlexNet有60 million个参数和65000个 神经元,五层卷积,三层全连接网络,最终的输出层是1000通道的softmax。AlexNet利用了两块GPU进行计算,大大提高了运算效率,并且在ILSVRC-2012竞赛中获得了top-5测试的15.3%error rate, 获得第二名的方法error rate 是 26.2%,可以说差距是非常的大了,足以说明这个网络在当时给学术界和工业界带来的冲击之大。

一些背景

在计算机视觉领域object detection & recognition 通常用机器学习的方法来解决。为了提高识别的效果,我们可以通过收集更多的可训练的数据来让模型的泛化性能提高。目前,在以一万为单位的数量级层面的数据(称为简单的识别任务)已经获得了非常好的性能,例如:MNIST 手写数字识别任务,最好的性能已经达到了<0.3%的误差。但是现实中的物体存在相当多的变化属性,所以学习识别它们需要更多的数据。事实上,小的图像训练数据有很多的缺点,无论以我们的直觉想还是理论证明都是有依据的,理论上论文《Why is real-world visual object recognition hard?》给出了研究方法。随着互联网技术的发展,以及智能手机的普及图像数据获取可以说越来越容易。所以就有组织去收集这些现实中事物的图像并进行标记和分割。例如:LabelMe(Labelme: a database and web-based tool for image annotation. ),包含了成百上千的全分割图像。 ImageNet(ImageNet: A Large-Scale Hierarchical Image Database. I),包含15 million 标记的高分辨率图像,包含超过了22000种现实中的事物。

文章中说该模型有5层卷积,去掉任意一层都会使结果不好,所以这个网络的深度似乎是很重要的,这样的话难免引起我们的思考,记得不知道哪位大神在一篇论文中证明了,神经网络可以模拟任意多项式,只要神经元数量足够多,并且和深度关系不大。但这里的实验却表示深度会对网络的性能有影响。

文章中还提到了,他们用5-6天训练了这个模型,并且限制了网络的大小,因为现有的硬件智能允许那么大的内存,用更好的设备还可以获得更好的效果。

网络结构

AlexNet 的网络结构是这样的。
在这里插入图片描述
首先这幅图分为上下两个部分的网络,论文中提到这两部分网络是分别对应两个GPU,只有到了特定的网络层后才需要两块GPU进行交互,这种设置完全是利用两块GPU来提高运算的效率,其实在网络结构上差异不是很大。为了更方便的理解,我们假设现在只有一块GPU或者我们用CPU进行运算,我们从这个稍微简化点的方向区分析这个网络结构。网络总共的层数为8层,5层卷积,3层全连接层。

第一层:卷积层1,输入为 224 × 224 × 3 224 \times 224 \times 3224×224×3的图像,卷积核的数量为96,论文中两片GPU分别计算48个核; 卷积核的大小为 11 × 11 × 3 11 \times 11 \times 311×11×3; stride = 4, stride表示的是步长, pad = 0, 表示不扩充边缘;
卷积后的图形大小是怎样的呢?
wide = (224 + 2 * padding - kernel_size) / stride + 1 = 54
height = (224 + 2 * padding - kernel_size) / stride + 1 = 54
dimention = 96
然后进行 (Local Response Normalized), 后面跟着池化pool_size = (3, 3), stride = 2, pad = 0 最终获得第一层卷积的feature map
最终第一层卷积的输出为
第二层:卷积层2, 输入为上一层卷积的feature map, 卷积的个数为256个,论文中的两个GPU分别有128个卷积核。卷积核的大小为:5 × 5 × 48 5 \times 5 \times 485×5×48; pad = 2, stride = 1; 然后做 LRN, 最后 max_pooling, pool_size = (3, 3), stride = 2;

第三层:卷积3, 输入为第二层的输出,卷积核个数为384, kernel_size = (3 × 3 × 256 3 \times 3 \times 2563×3×256), padding = 1, 第三层没有做LRN和Pool

第四层:卷积4, 输入为第三层的输出,卷积核个数为384, kernel_size = (3 × 3 3 \times 33×3), padding = 1, 和第三层一样,没有LRN和Pool

第五层:卷积5, 输入为第四层的输出,卷积核个数为256, kernel_size = (3 × 3 3 \times 33×3), padding = 1。然后直接进行max_pooling, pool_size = (3, 3), stride = 2;

第6,7,8层是全连接层,每一层的神经元的个数为4096,最终输出softmax为1000,因为上面介绍过,ImageNet这个比赛的分类个数为1000。全连接层中使用了RELU和Dropout。
上面的结构是假设在一块GPU上面的,和论文的两块GPU有差别,但是为了方便理解,还是采用越简单的结构越好。

在这里插入图片描述
在这里插入图片描述
上图是使用ReLUs和tanh作为激活函数的典型四层网络的在数据集CIFAR-10s实验中,error rate收敛到0.25时的收敛曲线,可以很明显的看到收敛速度的差距。虚线为tanh,实线是ReLUs。

Local Response Normalization(局部响应归一化)
在神经网络中,我们用激活函数将神经元的输出做一个非线性映射,但是tanh和sigmoid这些传统的激活函数的值域都是有范围的,但是ReLU激活函数得到的值域没有一个区间,所以要对ReLU得到的结果进行归一化。也就是Local Response Normalization。局部响应归一化的方法如下面的公式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们看上图,每一个矩形表示的一个卷积核生成的feature map。所有的pixel已经经过了ReLU激活函数,现在我们都要对具体的pixel进行局部的归一化。假设绿色箭头指向的是第i个个kernel对应的map,其余的四个蓝色箭头是它周围的邻居kernel层对应的map,假设矩形中间的绿色的pixel的位置为(x, y),那么我需要提取出来进行局部归一化的数据就是周围邻居kernel对应的map的(x, y)位置的pixel的值。也就是上面式子中的a ( x , y ) j a^j_{(x, y)}a
(x,y)
j

。然后把这些邻居pixel的值平方再加和。乘以一个系数α \alphaα再加上一个常数k,然后β \betaβ次幂,就是分母,分子就是第i个kernel对应的map的(x, y)位置的pixel值。这样理解之后我感觉就不是那么复杂了。

关键是参数α , β , k如何确定,论文中说在验证集中确定,最终确定的结果为:
k = 2 , n = 5 , α =10e-4, β = 0.75 .Overlapping Pooling(覆盖的池化操作)
一般的池化层因为没有重叠,所以pool_size 和 stride一般是相等的,例如8 × 8 8\times 88×8的一个图像,如果池化层的尺寸是2 × 2 2 \times 22×2,那么经过池化后的操作得到的图像是 4 × 4 4 \times 44×4大小,这种设置叫做不覆盖的池化操作,如果 stride < pool_size, 那么就会产生覆盖的池化操作,这种有点类似于convolutional化的操作,这样可以得到更准确的结果。在top-1,和top-5中使用覆盖的池化操作分别将error rate降低了0.4%和0.3%。论文中说,在训练模型过程中,覆盖的池化层更不容易过拟合。

Overall Architecture

网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。

卷积层C1
该层的处理流程是: 卷积–>ReLU–>池化–>归一化。

卷积,输入是227×227,使用96个11×11×3的卷积核,得到的FeatureMap为55×55×96。
ReLU,将卷积层输出的FeatureMap输入到ReLU函数中。
池化,使用3×3步长为2的池化单元(重叠池化,步长小于池化单元的宽度),输出为27×27×96((55−3)/2+1=27)
局部响应归一化,使用k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为27×27×96,输出分为两组,每组的大小为27×27×48
卷积层C2
该层的处理流程是:卷积–>ReLU–>池化–>归一化

卷积,输入是2组27×27×48。使用2组,每组128个尺寸为5×5×48的卷积核,并作了边缘填充padding=2,卷积的步长为1. 则输出的FeatureMap为2组,每组的大小为27×27 times128. ((27+2∗2−5)/1+1=27)
ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为(27−3)/2+1=13,输出为13×13×256
局部响应归一化,使用k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为13×13×256,输出分为2组,每组的大小为13×13×128
卷积层C3
该层的处理流程是: 卷积–>ReLU

卷积,输入是13×13×256,使用2组共384尺寸为3×3×256的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times384
ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
卷积层C4
该层的处理流程是: 卷积–>ReLU
该层和C3类似。

卷积,输入是13×13×384,分为两组,每组为13×13×192.使用2组,每组192个尺寸为3×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times384,分为两组,每组为13×13×192
ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
卷积层C5
该层处理流程为:卷积–>ReLU–>池化

卷积,输入为13×13×384,分为两组,每组为13×13×192。使用2组,每组为128尺寸为3×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13×256
ReLU,将卷积层输出的FeatureMap输入到ReLU函数中
池化,池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为 (13−3)/2+1=6,即池化后的输出为6×6×256
全连接层FC6
该层的流程为:(卷积)全连接 -->ReLU -->Dropout

卷积->全连接: 输入为6×6×256,该层有4096个卷积核,每个卷积核的大小为6×6×256。由于卷积核的尺寸刚好与待处理特征图(输入)的尺寸相同,即卷积核中的每个系数只与特征图(输入)尺寸的一个像素值相乘,一一对应,因此,该层被称为全连接层。由于卷积核与特征图的尺寸相同,卷积运算后只有一个值,因此,卷积后的像素层尺寸为4096×1×1,即有4096个神经元。
ReLU,这4096个运算结果通过ReLU激活函数生成4096个值
Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元
全连接层FC7
流程为:全连接–>ReLU–>Dropout

全连接,输入为4096的向量
ReLU,这4096个运算结果通过ReLU激活函数生成4096个值
Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元
输出层
第七层输出的4096个数据与第八层的1000个神经元进行全连接,经过训练后输出1000个float型的值,这就是预测结果。

AlexNet参数数量
卷积层的参数 = 卷积核的数量 * 卷积核 + 偏置

C1: 96个11×11×3的卷积核,96×11×11×3+96=34848
C2: 2组,每组128个5×5×48的卷积核,(128×5×5×48+128)×2=307456
C3: 384个3×3×256的卷积核,3×3×256×384+384=885120
C4: 2组,每组192个3×3×192的卷积核,(3×3×192×192+192)×2=663936
C5: 2组,每组128个3×3×192的卷积核,(3×3×192×128+128)×2=442624
FC6: 4096个6×6×256的卷积核,6×6×256×4096+4096=37752832
FC7: 4096∗4096+4096=16781312
output: 4096∗1000=4096000
卷积层 C2,C4,C5中的卷积核只和位于同一GPU的上一层的FeatureMap相连。从上面可以看出,参数大多数集中在全连接层,在卷积层由于权值共享,权值参数较少。

防止过拟合的方法

神经网络的一个比较严重的问题就是过拟合问题,论文中采用的数据扩充和Dropout的方法处理过拟合问题。

Data Augmentation(数据扩张,就是对原始数据做一些变化)
数据扩充是防止过拟合的最简单的方法,只需要对原始的数据进行合适的变换,就会得到更多有差异的数据集,防止过拟合。

Dropout
Dropout背后有很多有意思的东西,但是在这里我们不需要了解太深,只需要知道Dropout是在全连接层中去掉了一些神经节点,达到防止过拟合的目的,我们可以看上面的图在第六层和第七层都设置了Dropout。

最后附上源码:

#导入必要的pytorch包
import torch
import torch.nn as nn
class alexnet(nn.Module):
    
    def __init__(self, num_classes=1000):
        super(alexnet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64, 192, kernel_size=5, stride=1, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192, 384, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True)  ,  
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        self.avgpool = nn.AdaptiveAvgPool2d((6,6))
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(6*6*256, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes)
        )
    
    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        out = self.classifier(x)
        return out 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值