前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【卷积神经网络结构专题】一文详解AlexNet(附代码实现)

【卷积神经网络结构专题】一文详解AlexNet(附代码实现)

作者头像
深度学习技术前沿公众号博主
发布2020-06-01 11:45:37
4K0
发布2020-06-01 11:45:37
举报
文章被收录于专栏:深度学习技术前沿

【导读】本文是卷积神经网络结构系列专题第二篇文章,前面我们已经介绍了第一个真正意义上的卷积神经网络,那就是由发明者Lecun发明的LeNet,详细解读见:【卷积神经网络结构专题】一文详解LeNet(附代码实现)

但是在LeNet发明后的几十年时间,深度学习仍然处于低潮期,很少人去做研究。直到2012年AlexNet在ImageNet竞赛中以超过第二名10.9个百分点的绝对优势一举夺冠开始,深度学习和卷积神经网络一举成名。自此,深度学习的相关研究越来越多,一直火到了今天。下面这张图是历年来ImageNet的冠军方案所提出来的网络结构,本卷积神经网络结构专题也将沿着这张图来对网络架构依次解读。

AlexNet论文

  • 论文地址:http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf
  • 代码地址:https://github.com/rasbt/deeplearning-models

AlexNet网络结构

如上图所示,AlexNet网络架构的参数统计如下:

  • 卷积层:5层
  • 全连接层:3层
  • 池化层:3层
  • 深度:8层
  • 参数个数:60M
  • 神经元个数:650k
  • 分类数目:1000类

网络基本架构为:conv1 (96) -> pool1 -> conv2 (256) -> pool2 -> conv3 (384) -> conv4 (384) -> conv5 (256) -> pool5 -> fc6 (4096) -> fc7 (4096) -> fc8 (1000) -> softmax。AlexNet有着和LeNet-5相似网络结构,但更深、有更多参数。conv1使用11×11的滤波器、步长为4使空间大小迅速减小(227×227 -> 55×55)。

网络结构参数详细介绍:

从上图还可以看到网络有两个分支,这是由于当时的显卡容量问题,AlexNet 的60M个参数无法全部放在一张显卡上操作,所以采用了两张显卡分开操作的形式,其中在C3,R1,R2,R3层上出现交互,所谓的交互就是通道的合并,是一种串接操作。为了增强模型的泛化能力,避免过拟合的发生,论文使用了随机裁剪的方法将原始的的图像随机裁剪,得到尺寸为的图像,输入到网络训练。

AlexNet网络结构流程图

注意:数据输入时,图片大小为[224,224,3],第一个卷积层conv1的卷积核尺寸为,滑动步长为,卷积核数目为96。卷积后得到的输出矩阵维度为[96,55,55],值得注意的是如果直接按照卷积的定义来计算的话,那么输出特征的长宽应该是,这个值并不是,因此这里的值是将原图做了padding之后再进行卷积得到的,具体来说就是将原图padding到,这样再计算就是了。所以这一层的输出特征图维度就是[96,55,55]。

网络结构中每一层的具体操作:

AlexNet 中60M参数介绍:

AlexNet只有8层,但是它需要学习的参数有60000000个,相比如他的层数,这是一个很可怕的数字了,我们来计算下这些参数都是怎么来的:

C1:96×11×11×3(卷积核个数/宽/高/厚度) 34848个

C2:256×5×5×48(卷积核个数/宽/高/厚度) 307200个

C3:384×3×3×256(卷积核个数/宽/高/厚度) 884736个

C4:384×3×3×192(卷积核个数/宽/高/厚度) 663552个

C5:256×3×3×192(卷积核个数/宽/高/厚度) 442368个

R1:4096×6×6×256(卷积核个数/宽/高/厚度) 37748736个

R2:4096×4096 16777216个

R3:4096×1000 4096000个

在R1中卷积核尺寸是6×6×256而不是13×13×256是因为经过了最大池化。可以看到,全连接层(尤其是第一层)参数数量占了绝大部分。

AlexNet的创新点

1.使用了ReLU激活函数

AlexNet之前神经网络一般使用tanh或者sigmoid作为激活函数,sigmoid激活函数的表达式为: tanh激活函数的表达式为:

,这些激活函数在计算梯度的时候都比较慢,而AlexNet提出的ReLU表达式为: 。实验结果表明,要将深度网络训练至training error rate达到25%的话,ReLU只需5个epochs的迭代,但tanh单元需要35个epochs的迭代,用ReLU比tanh快6倍。

2.使用了随机失活(dropout)。

Dropout属于正则化技术中的一种,dropout的作用是增加网络的泛化能力,可以用在卷积层和全连接层。但是在卷积层一般不用dropout, dropout是用来防止过拟合的过多参数才会容易过拟合,卷积层参数本来就没有全连接层参数多,因此,dropout一般常用在全连接层。该方法通过让全连接层的神经元(该模型在前两个全连接层引入Dropout)以一定的概率失去活性(比如0.5)失活的神经元不再参与前向和反向传播,相当于约有一半的神经元不再起作用。

3.局部响应归一化(Local Response Normalization)

AlexNet中认为ReLU激活函数的值域没有一个固定的区间(sigmoid激活函数值域为(0,1)),所以需要对ReLU得到的结果进行归一化,这一点有点像之后的BN,都是改变中间特征图权重分布加速收敛。即论文提出的Local Response Normalization。

LPR作用原理:建立局部竞争机制,使局部较大值得到较大的响应,至于局部的范围是多大,可以通过超参数n进行选择相邻的核,定义想要的局部大小。这种归一化操作实现了某种形式的横向抑制。局部响应归一化的计算公式如下:

参数解释如下:

  • i :代表下标,即要计算的像素值的下标,从0开始开始算起。
  • j :代表平方累加索引,即从j~i的像素值平方求和。
  • x,y:代表像素中的位置,公式中用不到。
  • a:代表特征图里面i对应的像素值。
  • N:每个特征图最内层向量的列数。
  • k:超参数,由网络层中的blas指定。
  • alpha:超参数,由网络层中的alpha指定。
  • n/2:超参数,由网络层中的deepth_radius指定。
  • beta:超参数,由网络层中的belta指定。

4. 使用了很多数据增强技术

1. 第一种数据增强的方法是将原图片大小为256*256中随机的提取224*224的图片,以及他们水平方向的映像。

2. 第二种数据增强的方法就是在图像中每个像素的R、G、B值上分别加上一个数,用到的方法为PCA。数学表达式如下:

p是主成分,lamda是特征值,alpha是N(0,0.1)高斯分布中采样得到的随机值。此方案名义上得到自然图像的重要特性,也就是说,目标是不随着光照强度和颜色而改变的。

3. AlexNet训练采用的是SGD,每批图像大小为128,动力为0.9(SGD+momentum(0.9), weight decay)

基于Pytorch的AlexNet代码实现

代码语言:javascript
复制
class AlexNet(nn.Module):

    def __init__(self, num_classes):
        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, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, 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(0.5),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            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), 256 * 6 * 6)
        logits = self.classifier(x)
        probas = F.softmax(logits, dim=1)
        return logits, probas

参考链接:

  1. https://blog.csdn.net/chaipp0607/article/details/72847422
  2. https://zhuanlan.zhihu.com/p/31727402
  3. https://mp.weixin.qq.com/s/4nTRYbIZOLcMdqYpRpui6A
  4. https://blog.csdn.net/qq_38807688/article/details/84206655
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深度学习技术前沿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 网络结构参数详细介绍:
  • 1.使用了ReLU激活函数
  • 2.使用了随机失活(dropout)。
  • 3.局部响应归一化(Local Response Normalization)
  • 4. 使用了很多数据增强技术
  • 参考链接:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档