AlexNet论文总结与实现-2012

 

经典分类网络系列文章链接:

1、LeNet结构解析

2、AlexNet论文翻译AlexNet论文总结与实现

3、VGG论文翻译VGGNet总结及启发

ImageNet Classification with Deep Convolutional Neural Networks

文章虽然发表在12年,但文章中提到的Relu、Dropput,momentum、数据增广方式、10 paths测试法以及作者认为深度是非常重要的,这些都是现在神经网络的基础。很值得仔细阅读和理解。

1、特性/贡献

发表于2012年,在ImageNet测试数据上,我们得到了top-1 37.5%, top-5 17.0%的错误率,赢得了冠军并且与第二名 top-5 26.2%的错误率相比,我们取得了top-5 15.3%的错误率。

贡献(到目前为止仍在被使用的技巧):

1、使用Relu激活函数.

        Relu激活函数学习速率总是比饱和神经元网络快几倍。

2、引入Dropput,momentum(动量学习率)

        权重衰减:正则项,减少训练误差。

3、整体结构:

       input_shape = (224, 224, 3)

        主要优势:网络加深(相比lenet),5个conv+3个Dense+1个softmax

4、两种数据增广方式(至今仍是经典)

        改变图像位置:平移、翻转、随机剪裁;

        改变图像像素值,不改变位置:随机颜色变换;

        测试方式:10 paths测试法。

5、遵循启发式的方法(至今仍是经典)

所有的层使用相等的学习率,这个是在整个训练过程中我们手动调整得到的。当验证误差在当前的学习率下停止提供时,我们遵循启发式的方法将学习率除以10。学习率初始化为0.01,在训练停止之前降低三次

6、作者实验发现,认为深度是非常重要的。

2、文章中的一些见解

1)与具有层次大小相似的标准前馈神经网络,CNNs有更少的连接和参数,因此它们更容易训练,而它们理论上的最佳性能可能仅比标准前馈神经网络差一点;

2)最终的网络包含5个卷积层和3个全连接层,深度似乎是非常重要的:我们发现移除任何卷积层(每个卷积层包含的参数不超过模型参数的1%)都会导致更差的性能;

3、数据处理

训练时,将图像进行下采样到固定的256×256分辨率。给定一个矩形图像,我们首先缩放图像短边长度为256,然后从结果图像中裁剪中心的256×256大小的图像块。在训练集上对像素减去像素平均值。

即:等比例缩放至256,中心剪裁获取256*256的图像。

数据增强:

剪裁式数据增广:第一种数据增强方式包括产生图像变换和水平翻转。我们从256×256图像上通过随机提取224 × 224的图像块实现了这种方式,然后在这些提取的图像块上进行训练。这通过一个2048因子增大了我们的训练集,尽管最终的训练样本是高度相关的。没有这个方案,我们的网络会有大量的过拟合,这会迫使我们使用更小的网络。在测试时,网络会提取5个224 × 224的图像块(四个角上的图像块和中心的图像块)和它们的水平翻转(因此总共10个图像块)进行预测,然后对网络在10个图像块上的softmax层进行平均。

第二种数据增强方式包括改变训练图像的RGB通道的强度。具体地,我们在整个ImageNet训练集上对RGB像素值集合执行PCA。对于每幅训练图像,我们加上多倍找到的主成分,大小成正比的对应特征值乘以一个随机变量,随机变量通过均值为0,标准差为0.1的高斯分布得到。因此对于每幅RGB图像像素$I_xy = [I^R_{xy} , I^G_{xy} , I^B_{xy} ]^T$,我们加上下面的数量:

$p_i$,$\lambda_i$分别是RGB像素值3 × 3协方差矩阵的第$i$个特征向量和特征值,$\alpha_i$是前面提到的随机变量。对于某个训练图像的所有像素,每个$\alpha_i$只获取一次,直到图像进行下一次训练时才重新获取。这个方案近似抓住了自然图像的一个重要特性,即光照的颜色和强度发生变化时,目标身份是不变的。这个方案减少了top 1错误率1%以上。

即:随机剪裁使网络一定程度的克服数据上的过拟合,随机调整RGB颜色通道强度,使得top 1错误率减少1%以上。

4、网络结构

4.1、Relu非线性激活函数

Relu激活函数学习速率总是比饱和神经元网络快几倍。虚线是tanh激活训练曲线,实线是Relu激活函数。在CIFAR-10上,relu要比tanh从0.75错误率下降到0.25的错误率快上好几倍。

4.2、重叠池化

CNN中的池化层归纳了同一核映射上相邻组神经元的输出。习惯上,相邻池化单元归纳的区域是不重叠的(例如[17, 11, 4])。更确切的说,池化层可看作由池化单元网格组成,网格间距为 s 个像素,每个网格归纳池化单元中心位置 z × z 大小的邻居。如果设置 s = z ,我们会得到通常在CNN中采用的传统局部池化。如果设置 s < z ,我们会得到重叠池化。这就是我们网络中使用的方法,设置 s = 2 ,z = 3 。这个方案分别降低了top-1 0.4%,top-5 0.3%的错误率,与非重叠方案s = 2,z = 2相比,输出的维度是相等的。我们在训练过程中通常观察采用重叠池化的模型,发现它更难过拟合。

即:kernel_size=3, stride=2。top-1 错误率降低0.4%,且更难过拟合。

4.3、隐层局部归一化,BN,Dropput,动量学习率

Dropput:

将许多不同模型的预测结合起来是降低测试误差[1, 3]的一个非常成功的方法,但对于需要花费几天来训练的大型神经网络来说,这似乎太昂贵了。然而,有一个非常有效的模型结合版本,它只花费两倍的训练成本。这种最近引入的技术,叫做“dropout”[10],它会以0.5的概率对每个隐层神经元的输出设为0。那些“失活的”的神经元不再进行前向传播并且不参与反向传播。因此每次输入时,神经网络会采样一个不同的架构,但所有架构共享权重。这个技术减少了复杂的神经元互适应,因为一个神经元不能依赖特定的其它神经元的存在。因此,神经元被强迫学习更鲁棒的特征,它在与许多不同的其它神经元的随机子集结合时是有用的。

在测试时,我们使用所有的神经元但它们的输出乘以0.5,对指数级的许多失活网络的预测分布进行几何平均,这是一种合理的近似。

我们在图2中的前两个全连接层使用失活。如果没有失活,我们的网络表现出大量的过拟合。dropout大致上使要求收敛的迭代次数翻了一倍,训练速度为1/Dropout。

学习细节:

我们使用随机梯度下降来训练我们的模型,样本的batch size为128,动量为0.9,权重衰减为0.0005。我们发现少量的权重衰减对于模型的学习是重要的。换句话说,权重衰减不仅仅是一个正则项:它减少了模型的训练误差。权重 w 的更新规则是:

i 是迭代索引,v 是动量变量,e是学习率,e*(al/aw|wi)*Di是目标函数对 w ,在 w_i上的第 i 批微分 D_i的平均。

我们使用均值为0,标准差为0.01的高斯分布对每一层的权重进行初始化。我们在第2,4,5卷积层和全连接隐层将神经元偏置初始化为常量1。这个初始化通过为ReLU提供正输入加速了学习的早期阶段。我们在剩下的层将神经元偏置初始化为0。

我们对所有的层使用相等的学习率,这个是在整个训练过程中我们手动调整得到的。当验证误差在当前的学习率下停止提供时,我们遵循启发式的方法将学习率除以10。学习率初始化为0.01,在训练停止之前降低三次。我们在120万图像的训练数据集上训练神经网络大约90个循环,在两个NVIDIA GTX 580 3GB GPU上花费了五到六天。

5、网络结构

AlexNet诞生于2012年,主要优势是网络加深(5个卷积层+3个全连接层+1个softmax层),也是在那年之后,更多的更深的神经网路被提出。

第一层(卷积+池化):

输入:224*224*3大小的彩色原图,预处理为227*227*3的大小;

Conv1:96个11*11的卷积核,步长4, 输出图为55*55*96 (2个并行的48) ;(227-11)/4+1=55 ;

relu1:激活函数定义为ReLU(x)=max(x,0);

pooling1:3*3 pool,步长2,输出图为27*27*96;

第二层:

输入:27*27*96大小的特征图;

Conv2:256个5*5*96的卷积核,加边padding=2,图大小不变,步长1, 输出图为 27*27*256 (2个128并行) ; (27-5+2*2)/1+1=27;

relu2:激活函数定义为ReLU(x)=max(x,0);

pooling2:3*3 pool,步长2,输出图为13*13*256;

第三层:

输入:13*13*256大小的特征图;

Conv3:384个3*3*256的卷积核,加边,图大小不变,步长1, 输出图为13*13*384 (2个192并行) ;(13-3+2*1)/1+1=13

第四层:

输入:13*13*384大小的特征图;

Conv4:384个3*3*384的卷积核,加边,图大小不变,步长1, 输出图为13*13*384 (2个192并行) ; (13-3+2*1)/1+1=13

第五层:

输入:13*13*384大小的特征图;

Conv5:256个3*3*384的卷积核,步长2, 输出图为8*8*256 (2个128并行) ; (13-3+2*2)/2+1=8;

pooling5:2*2 pool,步长2,输出图为4*4*256;

全连接层:

输入:4*4*256的特征图,将4*4*256的特征图拉成一个4096的向量,即4096个节点;

隐层:同输入层节点数,即4096个节点 ;

输出:1000,表示有1000个类别;

 

特点:

卷积核大小:11*11->5*5->3*3->3*3->3*3,大小由大至小

隐层单元深度:96->256->256->384->256,从小至大再至小

特征图大小:224->55->27->13->13->8,倍数递减,至不变

6、实现

训练速度为1/Dropout,可进一步减少过拟合,BN在卷积激活层后添加。局部响应归一化(A-LRN网络)在没有任何归一化层的情况下,对模型VGG的A模型没有改善(VGG论文翻译)。在一些版本的实现用BN替代,这里示例代码不做填加。

import torch as t
import torch.nn as nn


class AlexNet(nn.Module):
    def __init__(self, num_classes):
        super(AlexNet, self).__init__()

        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 96, 11, 4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )

        self.layer2 = nn.Sequential(
            nn.Conv2d(96, 256, 5, 1, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )

        self.layer3 = nn.Sequential(
            nn.Conv2d(256, 384, 3, 1, padding=1),
            nn.ReLU(inplace=True),
        )

        self.layer4 = nn.Sequential(
            nn.Conv2d(384, 384, 3, 1, padding=1),
            nn.ReLU(inplace=True),
        )

        self.layer5 = nn.Sequential(
            nn.Conv2d(384, 256, 3, 2, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
        )

        self.classifier = nn.Sequential(
            nn.Dropout(0.5),
            nn.Linear(256 * 4 * 4, 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.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.layer5(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x


if __name__ == '__main__':
    x = t.randn(1, 3, 224, 224)
    model = AlexNet(1000)
    y = model(x)
    print("model:", model)
    print("y:", y.shape)
    pass

完整代码实现:https://github.com/alexzhang19/pytorch-classify/blob/master/models/alexnet.py

AlexNet全文翻译https://blog.csdn.net/weixin_34910922/article/details/107028880

展开阅读全文

Git 实用技巧

11-24
这几年越来越多的开发团队使用了Git,掌握Git的使用已经越来越重要,已经是一个开发者必备的一项技能;但很多人在刚开始学习Git的时候会遇到很多疑问,比如之前使用过SVN的开发者想不通Git提交代码为什么需要先commit然后再去push,而不是一条命令一次性搞定; 更多的开发者对Git已经入门,不过在遇到一些代码冲突、需要恢复Git代码时候就不知所措,这个时候哪些对 Git掌握得比较好的少数人,就像团队中的神一样,在队友遇到 Git 相关的问题的时候用各种流利的操作来帮助队友于水火。 我去年刚加入新团队,发现一些同事对Git的常规操作没太大问题,但对Git的理解还是比较生疏,比如说分支和分支之间的关联关系、合并代码时候的冲突解决、提交代码前未拉取新代码导致冲突问题的处理等,我在协助处理这些问题的时候也记录各种问题的解决办法,希望整理后通过教程帮助到更多对Git操作进阶的开发者。 本期教程学习方法分为“掌握基础——稳步进阶——熟悉协作”三个层次。从掌握基础的 Git的推送和拉取开始,以案例进行演示,分析每一个步骤的操作方式和原理,从理解Git 工具的操作到学会代码存储结构、演示不同场景下Git遇到问题的不同处理方案。循序渐进让同学们掌握Git工具在团队协作中的整体协作流程。 在教程中会通过大量案例进行分析,案例会模拟在工作中遇到的问题,从最基础的代码提交和拉取、代码冲突解决、代码仓库的数据维护、Git服务端搭建等。为了让同学们容易理解,对Git简单易懂,文章中详细记录了详细的操作步骤,提供大量演示截图和解析。在教程的最后部分,会从提升团队整体效率的角度对Git工具进行讲解,包括规范操作、Gitlab的搭建、钩子事件的应用等。 为了让同学们可以利用碎片化时间来灵活学习,在教程文章中大程度降低了上下文的依赖,让大家可以在工作之余进行学习与实战,并同时掌握里面涉及的Git不常见操作的相关知识,理解Git工具在工作遇到的问题解决思路和方法,相信一定会对大家的前端技能进阶大有帮助。
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值