经典网络-AlexNet论文及实践

2012-AlexNet

  • 论文地址: https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf
  • 项目地址:https://github.com/deep-diver/AlexNet

摘要

我们训练了一个大型的深度卷积神经网络,将ImageNetLSVRC-2010比赛中的120万张高分辨率图像分类为1000个不同的类别在测试数据上,获得了top-1和top-5的错误率分别为37.5%和17.0%,这明显优于之前的最先进水平。该神经网络有6000万个参数和65万个神经元,由5个卷积层组成(某些卷积层后面带有最大池化层),以及3个全连接层,最后是1000维度的softmax。为了加快训练速度,使用了非饱和神经元(ReLU)和一个非常有效的GPU实现的卷积操作。为了减少全连接层中的过拟合,采用了一种最近开发的正则化方法,称为“Dropout”,该方法被证明是非常有效的。还在ILSVRC-2012竞赛中输入了该模型的一个变体,赢得了关键,并且相较于第二名的测试错误率为26.2%,以15.3%的top-5测试错误率获得冠军。

1 序言

目前的目标识别方法主要利用了机器学习方法。为了提高它们的性能,我们可以收集更大的数据集,学习更强大的模型,并使用更好的技术来防止过拟合。直到最近,标记图像的数据集相对较小——成千上万的图像(例如,NORB[16]、Caltech-101/256[8,9]和CIFAR-10/100[12])。简单的识别任务可以用这种大小的数据集很好地解决,尤其是如果通过标签保留变换进行数据增强的情况下。例如,MNIST数字识别任务的当前最佳错误率(<0.3%)接近于人类性能[4]。但是在现实环境中的物体表现出相当大的可变性,所以要学会识别它们,有必要使用更大的训练集。事实上,小图像数据集的缺点已经被广泛认识到(例如,Pinto等人的[21]),但直到最近才有可能用数百万张图像收集标记数据集。新的更大的数据集包括LabelMe [23],它包含了数十万张完全分割的图像,ImageNet [6],它包含了22000个类别上的超过1500万张标注的高分辨率的图像。

为了从数百万张图像中学习数千个物体,需要一个具有较大学习能力的模型。然而,对象识别任务的巨大复杂性意味着即使这个问题被像ImageNet这样大的数据集也不能指定,所以我们的模型也应该有大量的先验知识来补偿我们没有的所有数据。卷积神经网络(CNNs)构成了这样一类模型[16,11,13,18,15,22,26],它的能力可以通过改变它们的深度和宽度来控制, 它们还可以对图像的性质(即统计数据的平稳性和像素依赖性的局部性)做出强有力的、最正确的假设。因此,与具有相似大小层的标准前馈神经网络相比,CNNs的连接和参数要少得多,因此它们更容易训练,而理论上的最佳性能可能只是仅比标准前馈神经网络稍微差一些。

尽管CNN具有引入注目的性能,尽管它们的局部架构相对高效,但它们的大规模应用于高分辨率图像仍然非常昂贵。幸运的是,当前的GPU,加上高度优化的二维卷积实现,足够强大,便于训练有趣的大型CNN,最近的数据集,最近的数据集例如ImageNet包含足够的标注样本来训练这样的模型而没有严重的过拟合。

本文的具体贡献如下:

  • 在ILSVRC-2010和ILSVRC-2012比赛[2]中使用ImageNet子集训练了迄今为止最大的卷积神经网络之一,并取得了迄今为止在这些数据集上报道过的最佳结果。
  • 编写了一个高度优化的GPU实现的二维卷积和训练卷积神经网络中固有的所有其他操作,并将其公开。
  • 设计网络包含了一些新的和不寻常的特性,这些特性提高神经网络的性能,并减少了其训练时间,详见第三节
  • 网络的规模使得过拟合成为一个重大的问题,即使有120万个标记的训练例子,所以使用了几种有效的技术来防止过拟合,详见第四节
  • 最终的网络包含5个卷积层和3个全连接层,该深度似乎是很重要的:我们发现移除任何卷积层(每个层包含不超过模型参数的1%)都会导致较差的性能

最后,网络的规模主要受到当前GPU可用内存和愿意容忍的训练时间的限制。设计的网络需要5到6天的时间才能在两个GTX580 3GB的GPU上进行训练。所有的实验都表明,只要等待更快的GPU和更大的数据集出现,结果就可以得到改进。

2 数据集

ImageNet是一个包含超过1500万张被标记的高分辨率图像的数据集,大约有22,000个类别。这些图片是从网上收集下来的,并使用Amazon’s Mechanical Turk的众包工具通过人工标注的。从2010年开始,作为Pascal视觉物体挑战的一部分,一个名为ImageNet大规模视觉识别挑战(ILSVRC)的年度竞赛已经举行。ILSVRC使用了ImageNet的一个子集,在1000个类别中,每个类别中有大约1000张图像。总共,大约有120万张训练图像,5万张验证图像和15万张测试图像。

ILSVRC-2010是ILSVRC中唯一可使用测试集标签的版本,所以我们大多数实验都是在这个版本上运行的。由于我们也使用了我们的模型参加了ILSVRC-2012竞赛,在第6节中,我们也报告了模型在这个版本的数据集上的结果,因为其测试集标签是不可用的。在ImageNet上,通常会报告两个错误率:top-1和top-5top-5错误率是指测试图像的正确标签不在模型认为的五个最可能的便签之中。

ImageNet包含各种分辨率的图像组成,而我们的系统需要一个恒定的输入维度。因此,将图像进行下采样到256×256的固定分辨率

  • 给定一个矩形图像,首先重新将图像缩放,使较短的一侧长度为256
  • 然后从结果图像中裁剪中心的的256×256图像块
  • 除了从每个像素中减去训练集上的均值之外,不对图像做任何其他方式的预处理。

所以,根据像素的(中心)原始RGB值来训练网络。

3 架构

图2总结了我们的网络的体系架构,它包含8个学习层——5个卷积层和3个完全连接层。下面,将描述我们的网络架构的一些新颖或不寻常的特征。第3.1-3.4节按照我们对其重要性的估计进行排序,最重要的放在最开始。

3.1 ReLU非线性

将神经元的输出f作为其输入x的函数进行建模的标准方法是用 f ( x ) = t a n h ( x ) f(x)=tanh(x) f(x)=tanh(x) f ( x ) = ( 1 + e − x ) − 1 f(x)=(1+e^{−x})^{−1} f(x)=(1+ex)1在梯度下降的训练时间方面,这些饱和非线性比非饱和非线性 f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0x) 要慢得多。在Nair和Hinton[20]之后,我们将具有这种非线性的神经元称为整正线性单位(ReLUs)使用ReLUs的深度卷积神经网络的训练速度比使用tanh单位的同类神经网络快几倍。如图1所示,它显示了对于一个特定的四层卷积网络,在CIFAR-10数据集上达到25%的训练误差所需的迭代次数。这幅图表明,如果我们使用传统的饱和神经元模型,我们就不可能用如此大型的神经网络进行实验。

经典网络-AlexNet论文及实践_第1张图片

使用ReLU的四层卷积神经网络在CIFAR-10数据集上达到25%的训练误差比使用tanh神经元的等价网络(虚线)快六倍。为了使训练尽可能快,每个网络的学习率是单独选择的。没有采用任何类型的正则化。影响的大小随着网络结构的变化而变化,这一点已得到证实,但使用ReLU的网络都比等价的饱和神经元快几倍。

经典网络-AlexNet论文及实践_第2张图片

我们并不是第一个考虑在CNN中替代传统神经元模型的人。例如,Jarrett等人[11]声称,非线性 f ( x ) = a b s ( t a n h ( x ) ) f(x)=abs(tanh(x)) f(x)=abs(tanh(x))与其对比归一化一起,然后是局部平均池化,在Caltech-101数据集上工作的非常好。然而,在这个数据集上,主要关注的是防止过拟合,因此它们所观察到的效果不同于在使用relu时报告的加速拟合训练集的能力。更快的学习对在大数据集上训练的大模型的性能有很大的影响。

3.2 多GPU训练

单个GTX580 GPU只有3GB的内存,这限制了可以用来训练它的网络的最大尺寸。事实证明,120万个图像用来进行网络训练是足够的,但那些太大的网络是无法而无法在单个GPU上进行训练的。因此,我们将网络分散在两个GPU上。 当前的GPU特别适合于跨GPU并行化,因为它们能够直接读取和写入彼此的内存,而不需要经过主机内存。我们所采用的并行化方案基本上是每个GPU上放置一半的内核(或神经元),另外还有一个技巧:只在某些特定的层上进行GPU通信。 这意味着,例如,第3层的内核会将第2层的所有内核映射作为输入。然而,第4层中的内核只从位于同一GPU上的第3层中的内核映射作为输入。选择连接模式是交叉验证的一个问题,但这允许我们精确地调整通信量,直到它的计算量在可接受的范围内。

除了我们的列不是独立的(见图2), 最终的架构有点类似于Ciresan等人[5]采用的“columnar” CNN。与每个卷积层一半的核在单GPU上训练的网络相比,该方案将top-1和top-5的错误率分别降低了1.7%和1.2%双GPU网络比单GPU网络稍微减少了训练时间。

经典网络-AlexNet论文及实践_第3张图片

CNN架构图解,明确描述了两个GPU之间的责任。在图的顶部,一个GPU运行在部分层上,而在图的底部,另一个GPU运行在部分层上。GPU只在特定的层进行通信。网络的输入是150,528维,网络剩下层的神经元数目分别是253,440–186,624–64,896–64,896–43,264–4096–4096–1000(8层)。

3.3 局部响应归一化|LRN

ReLUs具有一个理想的特性,即它们不需要输入归一化来防止饱和。如果至少有一些训练例子对ReLU产生了积极的输入,学习将在该神经元中发生。然而,我们仍然发现以下的局部响应归一化方案有助于泛化。用 a x , y i a_{x,y}^i ax,yi 表示在位置(x,y)应用核i,然后应用ReLU非线性,响应归一化激活 b x , y i b_{x,y}^i bx,yi由下面的表达式给出

在这里插入图片描述

其中,求和运算在N个“毗邻的”核映射的同一位置上执行,N是该层中的核总数。 核映射的顺序当然是任意的,并且在训练开始之前就已经确定。这种反应标准化实现了一种侧抑制(指的是被激活的神经元抑制相邻神经元),灵感来自于在真实神经元中发现的类型,在使用不同内核计算的神经元输出之间创造了较大活动的竞争。常数k、n、α和β是超参数,其值通过验证集确定;使用了k=2,n=5,α=10−4和β=0.75。 在某些层中应用ReLU非线性后,应用了这种归一化方法(见第3.5节)。

这个方案与Jarrett等人[11]的局部对比度归一化方案有一定的相似性,但我们更恰当的称其为 “亮度归一化”,因此我们没有减去均值响应归一化分别减少了top-1 1.4%top-5 1.2%的错误率。我们也在CIFAR-10数据集上验证了这个方案的有效性:一个没有使用归一化的四层CNN取得了13%的错误率,而使用归一化取得了11%的错误率。

3.4 重叠池化

CNN中的池化层总结了同一核图中相邻神经元组的输出。传统上,由相邻的池单元归纳的区域是不重叠的(例如[17,11,4])。更准确地说,池化层可以被认为是由一个间隔s像素的池化单元组成,每个单元总结一个以池化单元位置为中心的大小为z×z的邻域。

经典网络-AlexNet论文及实践_第4张图片

  • 如果设置s=z,就得到CNN中常用的传统局部池。
  • 如果设置s,得到重叠池。这是我们在整个网络中使用的方法,包括s=2z=3。在池化的时候,每次移动的步长小于池化的窗口长度。
  • 与非重叠方案的s=2、z=2相比,该方案将top-1和top-5的错误率分别降低了0.4%和0.3%。
  • 另外在训练过程中观察到,具有重叠池的模型发现过拟合稍微困难一些。

3.5 整体架构

现在准备描述我们的CNN的整体架构。如图2所示,网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。我们的网络最大化多项逻辑回归的目标,这等价于最大化预测分布下训练样本正确标签的对数概率的均值。

第2,4,5卷积层的核只与位于同一GPU上的前一层的核映射相连接第3卷积层的核与第2层的所有核映射相连。全连接层的神经元与前一层的所有神经元相连。 第1,2卷积层之后是响应归一化层。3.4节描述的这种最大池化层在响应归一化层和第5卷积层之后。ReLU非线性应用在每个卷积层和全连接层的输出上。

  • 第1卷积层使用96个核对224×224×3的输入图像进行滤波,核大小为11×11×3,步长是4个像素(核映射中相邻神经元感受野中心之间的距离)
  • 第2卷积层使用用第1卷积层的输出(响应归一化和池化)作为输入,并使用256个核进行滤波,核大小为5×5×48
  • 第3,4,5卷积层互相连接,中间没有接入池化层或归一化层。第3卷积层有384个核,核大小为3×3×256,与第2卷积层的输出(归一化的,池化的)相连。第4卷积层有384个核,核大小为3×3×192,第5卷积层有256个核,核大小为3×3×192
  • 每个全连接层有4096个神经元

经典网络-AlexNet论文及实践_第5张图片

4 减少过拟合

我们的神经网络架构有6000万个参数。尽管ILSVRC的1000类使每个训练示例对从图像到标签的映射施加了10比特的约束,但在没有相当大的过拟合的情况下,这不足以学习如此多的参数。下面,将描述我们对抗过拟合的两种主要方法。

4.1 数据增强

图像数据上最简单常用的用来减少过拟合的方法是使用标签保留变换(例如[25, 4, 5])来人工增大数据集。我们使用了两种独特的数据增强方式,这两种方式都可以从原始图像通过非常少的计算量产生变换的图像,因此变换图像不需要存储在硬盘上。在我们的实现中,变换图像通过CPU的Python代码生成,而此时GPU正在训练前一批图像。 因此,实际上这些数据增强方案是计算免费的。

  • 第一种数据增强方式包括产生图像变换和水平翻转。从256×256图像上通过随机提取224 × 224的图像块实现了这种方式,然后在这些提取的图像块上进行训练。这通过一个2048因子( ( 256 − 224 ) 2 × 2 = 2048 (256-224)^2×2=2048 (256224)2×2=2048)增大了训练集,尽管最终的训练样本是高度相关的若没有这个方案,我们的网络会有大量的过拟合,这会迫使我们使用更小的网络。在测试时,网络会提取5个224 × 224的图像块(四个角上的图像块和中心的图像块)和水平翻转(因此总共10个图像块)进行预测,然后对网络在10个图像块上的softmax层进行平均。(为什么使用224x224,而不是256x256,就是为了多弄出一些图片来

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

在这里插入图片描述

其中, p i p_i pi λ i λ_i λi分别为RGB像素值的3×3协方差矩阵的特征向量和特征值, α i α_i αi为上述随机变量。每个 α i α_i αi只对一个特定训练图像的所有像素绘制一次,直到该图像再次用于训练,此时它被重新绘制。该方案近似地捕捉到了自然图像的一个重要特性,即物体的身份对照明的强度和颜色的变化是不变的该方案将top-1的错误率降低了1%以上。

经典网络-AlexNet论文及实践_第6张图片

4.2 Dropout

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

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

经典网络-AlexNet论文及实践_第7张图片

5 学习细节

使用随机梯度下降来训练我们的模型批量大小(batch_size)为128,动量为0.9,权重衰减为0.0005。 我们发现,这少量的重量衰减对模型的学习很重要。换句话说,权重衰减不仅仅是一个正则化器:它减少了模型的训练误差。 重量w的更新规则为

在这里插入图片描述

  • 其中i是迭代指数,v是动量变量,e是学习速率,第三项是目标对第i ‘ w ‘ 的 导 数 的 `w`的导数的 wD_i$平均值

  • 更新wi

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

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

6 结果

在ILSVRC-2010上的结果如表1所示。神经网络取得了top-1 37.5%top-5 17.0%的错误率。而使用对6个在不同特征上训练的稀疏编码模型生成的预测进行平均的方法,在ILSVRC-2010竞赛中最佳结果是top-1 47.1%top-5 28.2%;使用在Fisher向量(FV, Fisher向量是通过两种密集采样特征计算得到的[24])上训练的两个分类器的预测结果进行评价的方法,公布的最好结果是top-1 45.7%top-5 25.7%

经典网络-AlexNet论文及实践_第8张图片

表1:ILSVRC-2010测试集上的结果对比。斜体是其它人取得的最好结果。

我们也用设计模型参加了ILSVRC-2012竞赛,结果如表2所示。由于ILSVRC-2012的测试集标签不能公开得到,我们不能报告我们尝试的所有模型的测试错误率。在这段的其余部分,我们会使用验证误差率和测试误差率互换,因为在我们的实验中它们的差别不会超过0.1%(看图2)。本文中描述的CNN取得了top-5 18.2%的错误率。五个类似的CNN预测的平均误差率为16.4%。为了对ImageNet 2011秋季发布的整个数据集(1500万图像,22000个类别)进行分类,我们在最后的池化层之后有一个额外的第6卷积层,训练了一个CNN,然后在它上面进行“fine-tuning”,在ILSVRC-2012取得了16.6%的错误率。对在ImageNet 2011秋季发布的整个数据集上预训练的两个CNN和前面提到的五个CNN的预测进行平均得到了15.3%的错误率。第二名的最好竞赛输入取得了26.2%的错误率,其方法是对FV上训练的一些分类器的预测结果进行平均,FV是在不同类型密集采样特征计算得到的。

经典网络-AlexNet论文及实践_第9张图片

表2:ILSVRC-2012验证集和测试集的误差对比。斜线部分是其它人取得的最好的结果。带星号的是“预训练的”对ImageNet 2011秋季数据集进行分类的模型。

最后,也报告了我们在ImageNet 2009秋季数据集上的误差率,ImageNet 2009秋季数据集有10,184个类,890万图像。在这个数据集上按照惯例用一半的图像来训练,一半的图像来测试。由于没有建立测试集,我们的数据集分割肯定不同于以前作者的数据集分割,但这对结果没有明显的影响。我们在这个数据集上的的top-1和top-5错误率是67.4%和40.9%,使用的网络模型是上面描述的在最后的池化层之后有一个额外的第6卷积层网络。这个数据集上公开可获得的最好结果是78.1%和60.9%[19]。

6.1 定性评估

图3显示了网络的两个数据连接层学习到的卷积核。网络学习到了大量的频率核、方向选择核,也学到了各种颜色点。注意两个GPU表现出的专业化,3.5小节中描述的受限连接的结果。GPU 1上的核主要是没有颜色的,而GPU 2上的核主要是针对颜色的这种专业化在每次运行时都会发生,并且是与任何特别的随机权重初始化(以GPU的重新编号为模)无关的

经典网络-AlexNet论文及实践_第10张图片

第一卷积层在224×224×3的输入图像上学习到的大小为11×11×3的96个卷积核。

上面的48个核是在GPU 1上学习到的

而下面的48个卷积核是在GPU 2上学习到的

在图4的左边部分,通过在8张测试图像上计算它的top-5预测定性地评估了网络学习到的东西。注意到,即使是不在图像中心的目标也能被网络识别,例如左上角的小虫。大多数的top-5标签似乎是合理的。例如,对于美洲豹来说,只有其它类型的猫被认为是看似合理的标签。在某些案例(格栅,樱桃)中,网络在意的图片焦点真的很模糊。

经典网络-AlexNet论文及实践_第11张图片

图4:

(左)8张ILSVRC-2010测试图像和我们的模型认为最可能的5个标签。每张图像的下面是它的正确标签,正确标签的概率用红条表示(如果正确标签在top 5中)。

(右)第一列是5张ILSVRC-2010测试图像。剩下的列展示了6张训练图像,这些图像在最后的隐藏层的特征向量与测试图像的特征向量有最小的欧氏距离。

另一种探测网络视觉知识的方法是考虑由一幅图像在最后的4096维隐藏层上所引起的特征激活如果两幅图像产生的特征激活向量具有较小的欧几里得距离,我们可以说,更高级级的神经网络认为它们是相似的。图4显示了来自测试集的5张图像和来自训练集的6张图像,根据这个测量方法,它们与每个图像最相似。注意,在像素级,检索到的训练图像在L2上通常不接近第一列中的查询图像。例如,检索出来的狗和大象会呈现出各种姿势。

通过两个4096维实值向量间的欧氏距离来计算相似性是效率低下的,但通过训练一个自动编码器将这些向量压缩为短二值编码可以使其变得高效。这应该会产生一种比将自动编码器应用到原始像素上[14]更好的图像检索方法,自动编码器应用到原始像素上的方法没有使用图像标签,因此会趋向于检索与要检索的图像具有相似边缘模式的图像,无论它们是否是语义上相似。

7 探讨

我们的结果表明一个大型深度卷积神经网络在一个具有高度挑战性的数据集上使用纯有监督学习可以取得破纪录的结果。值得注意的是,如果移除一个卷积层,网络的性能会降低。例如,移除任何中间层都会引起网络损失大约2%的top-1性能。因此深度对于实现我们的结果非常重要

为了简化实验,我们没有使用任何无监督的预训练,尽管我们希望它会有所帮助,特别是在如果我们能获得足够的计算能力来显著增加网络的大小而标注的数据量没有对应增加的情况下。到目前为止,我们的结果已经提高了,因为我们的网络更大、训练时间更长,但与人类视觉系统的颞线通路( infero-temporal pathway)相比,我们仍然有比较大的差距。最后我们想在视频序列上使用非常大的深度卷积网络,视频序列的时序结构会提供非常有帮助的信息,这些信息在静态图像上是缺失的或远不那么明显。

References

  • [1] R.M. Bell and Y. Koren. Lessons from the netflflix prize challenge. ACM SIGKDD Explorations Newsletter,9(2):75–79, 2007.

  • [2] A. Berg, J. Deng, and L. Fei-Fei. Large scale visual recognition challenge 2010. www.imagenet.org/challenges. 2010.

  • [3] L. Breiman. Random forests. Machine learning, 45(1):5–32, 2001.

  • [4] D. Cire¸san, U. Meier, and J. Schmidhuber. Multi-column deep neural networks for image classifification. Arxiv preprint arXiv:1202.2745*, 2012.

  • [5] D.C. Cire¸san, U. Meier, J. Masci, L.M. Gambardella, and J. Schmidhuber. High-performance neural networks for visual object classifification. Arxiv preprint arXiv:1102.0183, 2011.

  • [6] J. Deng, W. Dong, R. Socher, L.-J. Li, K. Li, and L. Fei-Fei. ImageNet: A Large-Scale Hierarchical Image Database. In CVPR09, 2009.

  • [7] J. Deng, A. Berg, S. Satheesh, H. Su, A. Khosla, and L. Fei-Fei. ILSVRC-2012, 2012. URL http://www.image-net.org/challenges/LSVRC/2012/.

  • [8] L. Fei-Fei, R. Fergus, and P. Perona. Learning generative visual models from few training examples: An incremental bayesian approach tested on 101 object categories. Computer Vision and Image Understanding, 106(1):59–70, 2007.

  • [9] G. Griffifin, A. Holub, and P. Perona. Caltech-256 object category dataset. Technical Report 7694, California Institute of Technology, 2007. URL http://authors.library.caltech.edu/7694.

  • [10] G.E. Hinton, N. Srivastava, A. Krizhevsky, I. Sutskever, and R.R. Salakhutdinov. Improving neural networks by preventing co-adaptation of feature detectors. arXiv preprint arXiv:1207.0580, 2012.

  • [11] K. Jarrett, K. Kavukcuoglu, M. A. Ranzato, and Y. LeCun. What is the best multi-stage architecture for object recognition? In International Conference on Computer Vision, pages 2146–2153. IEEE, 2009.

  • [12] A. Krizhevsky. Learning multiple layers of features from tiny images. Master’s thesis, Department of Computer Science, University of Toronto, 2009.

  • [13] A. Krizhevsky. Convolutional deep belief networks on cifar-10. Unpublished manuscript, 2010.

  • [14] A. Krizhevsky and G.E. Hinton. Using very deep autoencoders for content-based image retrieval. In ESANN, 2011.

  • [15] Y. Le Cun, B. Boser, J.S. Denker, D. Henderson, R.E. Howard, W. Hubbard, L.D. Jackel, et al. Handwritten digit recognition with a back-propagation network. In Advances in neural information processing systems, 1990.

  • [16] Y. LeCun, F.J. Huang, and L. Bottou. Learning methods for generic object recognition with invariance to pose and lighting. In Computer Vision and Pattern Recognition, 2004. CVPR 2004. Proceedings of the 2004 IEEE Computer Society Conference on*, volume 2, pages II–97. IEEE, 2004.

  • [17] Y. LeCun, K. Kavukcuoglu, and C. Farabet. Convolutional networks and applications in vision. In Circuits and Systems (ISCAS), Proceedings of 2010 IEEE International Symposium on, pages 253–256. IEEE, 2010.

  • [18] H. Lee, R. Grosse, R. Ranganath, and A.Y. Ng. Convolutional deep belief networks for scalable unsupervised learning of hierarchical representations. In Proceedings of the 26th Annual International Conference on Machine Learning*, pages 609–616. ACM, 2009.

  • [19] T. Mensink, J. Verbeek, F. Perronnin, and G. Csurka. Metric Learning for Large Scale Image Classifification: Generalizing to New Classes at Near-Zero Cost. In ECCV - European Conference on Computer Vision, Florence, Italy, October 2012.

  • [20] V. Nair and G. E. Hinton. Rectifified linear units improve restricted boltzmann machines. In Proc. 27th International Conference on Machine Learning*, 2010.

  • [21] N. Pinto, D.D. Cox, and J.J. DiCarlo. Why is real-world visual object recognition hard? PLoS computational biology, 4(1):e27, 2008.

  • [22] N. Pinto, D. Doukhan, J.J. DiCarlo, and D.D. Cox. A high-throughput screening approach to discovering good forms of biologically inspired visual representation. PLoS computational biology, 5(11):e1000579, 2009.

  • [23] B.C. Russell, A. Torralba, K.P. Murphy, and W.T. Freeman. Labelme: a database and web-based tool for image annotation. International journal of computer vision, 77(1):157–173, 2008.

  • [24] J. Sánchez and F. Perronnin. High-dimensional signature compression for large-scale image classifification. In Computer Vision and Pattern Recognition (CVPR), 2011 IEEE Conference on, pages 1665–1672. IEEE, 2011.

  • [25] P.Y. Simard, D. Steinkraus, and J.C. Platt. Best practices for convolutional neural networks applied to visual document analysis. In Proceedings of the Seventh International Conference on Document Analysis and Recognition*, volume 2, pages 958–962, 2003.

  • [26] S.C. Turaga, J.F. Murray, V. Jain, F. Roth, M. Helmstaedter, K. Briggman, W. Denk, and H.S. Seung. Convolutional networks can learn to generate affifinity graphs for image segmentation. Neural Computation, 22(2):511–538, 2010.

实践

以cifar-10数据为例,tensorflow v2 版本中的keras实现 Alexnet训练与预测

导入相关的包

import os
import sys
import time
import numpy as np
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow import keras

准备数据

cifar10数据集包含60,000个彩色图像,每个彩色图像具有尺寸32x32px。数据集中的图像的内容是从10个类中采样的。

(train_images, train_labels), (test_images, test_labels) = keras.datasets.cifar10.load_data()

CLASS_NAMES = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

validation_images, validtion_labels = train_images[:5000], train_labels[:5000]
train_images, train_labels = train_images[5000:], train_labels[5000:]

train_ds = tf.data.Dataset.from_tensor_slices((train_images, train_labels))
test_ds = tf.data.Dataset.from_tensor_slices((test_images, test_labels))
valid_ds = tf.data.Dataset.from_tensor_slices((validation_images, validtion_labels))

每个元素是一个字典,包含两个键(images,labels)

预处理数据

1 查看数据

plt.figure(figsize=(20, 20))
for i, (image, label) in enumerate(train_ds.take(5)):
    ax = plt.subplot(5, 5, i+1)
    plt.imshow(image)
    plt.title(CLASS_NAMES[label.numpy()[0]])
    plt.axis('off')

2 归一化数据

def process_images(image, label):
    image = tf.image.per_image_standardization(image)
    image = tf.image.resize(image, (227, 227))
    return image, label

这里尺寸不是论文中的224x224 而是227x227,是在运算中227更加合适一些,AndrewG 老师课程中说了一下。

  • tf.image.per_image_standardization: 图像标准化函数,归一化到均值为0,方差为1
  • tf.image.resize:调整图像尺寸

3.准备batch数据

train_ds_size = tf.data.experimental.cardinality(train_ds).numpy()  # 返回data的基数,并转成np格式
test_ds_size = tf.data.experimental.cardinality(test_ds).numpy()
valid_ds_size = tf.data.experimental.cardinality(valid_ds).numpy()

train_ds = (train_ds
                  .map(process_images)
                  .shuffle(buffer_size=train_ds_size)
                  .batch(batch_size=32, drop_remainder=True))

test_ds = (test_ds
                  .map(process_images)
                  .shuffle(buffer_size=train_ds_size)
                  .batch(batch_size=32, drop_remainder=True))

valid_ds = (valid_ds
                  .map(process_images)
                  .shuffle(buffer_size=train_ds_size)
                  .batch(batch_size=32, drop_remainder=True))

这里用到了tf.data.Dataset的一些性质:

  • map:对所有数据执行相应的操作;
  • shuffle:打乱数据,buffer_size等于整个数据的大小
  • batch:将此数据集的连续元素组合成批次,如果需要确定固定大小的输入,drop_remainder是设置为True;以免整除不断的情况剩余的部分输入

搭建网络和训练

这里用BatchNormlization代替LRN

  • 搭建网络
model = keras.models.Sequential([
    keras.layers.Conv2D(filters=96, kernel_size=(11,11), strides=(4,4), activation='relu', input_shape=(227,227,3)),
    keras.layers.BatchNormalization(),
    keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),
    
    keras.layers.Conv2D(filters=256, kernel_size=(5,5), strides=(1,1), activation='relu', padding="same"),
    keras.layers.BatchNormalization(),
    keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),
    
    keras.layers.Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), activation='relu', padding="same"),
    
    keras.layers.Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), activation='relu', padding="same"),
    
    keras.layers.Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding="same"),
    keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),
    
    keras.layers.Flatten(),
    keras.layers.Dense(4096, activation='relu'),
    keras.layers.Dropout(0.5),
    
    keras.layers.Dense(4096, activation='relu'),
    keras.layers.Dropout(0.5),
    
    keras.layers.Dense(10, activation='softmax')
])
  • 训练参数设置以及训练
root_logdir = os.path.join(os.curdir, "logs/")
def get_run_logdir():
    run_id = time.strftime("run_%Y_%m_%d-%H_%M_%S")
    return os.path.join(root_logdir, run_id)

model.compile(loss='sparse_categorical_crossentropy', optimizer=tf.optimizers.SGD(lr=0.001), metrics=['accuracy'])
model.summary()
history = model.fit(
    train_ds, epochs=10, validation_data=valid_ds,
    validation_freq=1, callbacks=[tensorboard_cb])

查看训练结果与测试

  • 查看训练曲线
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

plt.subplot(1, 2, 1)
plt.plot(acc, label='train acc')
plt.plot(val_acc, label='val acc')
plt.title('train and val acc')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(loss, label='train loss')
plt.plot(val_loss, label='val loss')
plt.title('train and val loss')
plt.legend()
plt.show()

经典网络-AlexNet论文及实践_第12张图片

或者使用tensorboard查看

tensorboard --logdir logs/xxx --bind_all

经典网络-AlexNet论文及实践_第13张图片

可以看到,随着迭代次数的增加,性能还在变好,这里只设置了迭代10次;

  • 评估模型性能
model.evaluate(test_ds)

[0.9347690939903259, 0.6739783883094788]

第一项是测试集的loss,第二项是测试集的准确率acc

  • 保存模型
model.save_weights('./checkpoints/alnext_checkpoint')

基于PyTorch实现:

import os
import sys
import time
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import torch.nn as nn
import torch.nn.functional as f
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader

# 配置GPU环境
os.environ['CUDA_VISIABLE_DIVICES'] = '0'

# 配置其他超参数
batch_size = 32
num_works = 4
lr = 1e-4
epochs = 20


# 数据加载
from torchvision import datasets

train_data = datasets.CIFAR10(root='./', train=True, download=True, transform=data_transform)
test_data = datasets.CIFAR10(root='./', train=False, download=True, transform=data_transform)

image, label = next(iter(train_loader))
print(image.shape, label.shape)

plt.imshow(image[0][0], cmap='gray')

PyTorch以sequnetial形式构建网络:

class AlexNet(nn.Module):
    def __init__(self, num_classes=1000, dropout_ratio=0.5):
        super().__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=96, kernel_size=11, stride=4),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, groups=2, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        
        self.layer3 = nn.Sequential(
            nn.Conv2d(in_channels=256, out_channels=384, padding=1, kernel_size=3),
            nn.ReLU(inplace=True)
        )
        self.layer4 = nn.Sequential(
            nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True)
        )
        
        self.layer5 = nn.Sequential(
            nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2)
        )
        
         #需要针对上一层改变view
        self.layer6 = nn.Sequential(
            nn.Linear(in_features=6*6*256, out_features=4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=dropout_ratio)
        )
        self.layer7 = nn.Sequential(
            nn.Linear(in_features=4096, out_features=4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=dropout_ratio)
        )
        
        self.layer8 = nn.Linear(in_features=4096, out_features=num_classes)
        
    def forward(self, x):
        x = self.layer5(self.layer4(self.layer3(self.layer2(self.layer1(x)))))
        x = x.view(-1, 6*6*256)
        x = self.layer8(self.layer7(self.layer6(x)))
        
        return x

model = AlexNet(1000, 0.5)
model = model

# 设定损失函数
ceriterion = nn.CrossEntropyLoss()

# 设定优化器
optimizer = optim.Adam(model.parameters(), lr=lr)


def train(epoch):
    model.train()
    train_loss = 0
    for data, label in train_loader:
        # data, label = data.cuda(), label.cuda()
        optimizer.zero_grad()
        output = model(data)
        loss = ceriterion(output, label)
        loss.backward()
        optimizer.step()
        train_loss += loss.item() * data.size(0)
    train_loss = train_loss / len(train_loader.dataset)
    print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))

def val(epoch):
    # 设置评估状态
    model.eval()
    val_loss = 0
    gt_labels = []
    pred_labels = []
    # 不设置梯度
    with torch.no_grad():
        for data, label in test_loader:
            # data, label = data.cuda, label.cuda()
            output = model(data)
            preds = torch.argmax(output, 1)
            gt_labels.append(label.cpu().data.numpy())
            pred_labels.append(preds.cpu().data.numpy())
            loss = ceriterion(output, label)
            val_loss += loss.item()*data.size(0)
    # 计算验证集的平均损失
    val_loss = val_loss /len(test_loader.dataset)
    gt_labels, pred_labels = np.concatenate(gt_labels), np.concatenate(pred_labels)
    # 计算准确率
    acc = np.sum(gt_labels ==pred_labels)/len(pred_labels)
    print('Epoch: {} \tValidation Loss: {:.6f}, Accuracy: {:6f}'.format(epoch, val_loss, acc))

训练和评估

for epoch in range(1, epochs+1):
    train(epoch)
    val(epoch)
Epoch: 1 	Training Loss: 1.138104
Epoch: 1 	Validation Loss: 1.028532, Accuracy: 0.638700
Epoch: 2 	Training Loss: 0.870970
Epoch: 2 	Validation Loss: 0.768581, Accuracy: 0.734200
Epoch: 3 	Training Loss: 0.702137
Epoch: 3 	Validation Loss: 0.686814, Accuracy: 0.759500
Epoch: 4 	Training Loss: 0.575243
Epoch: 4 	Validation Loss: 0.641346, Accuracy: 0.778400
Epoch: 5 	Training Loss: 0.469130
Epoch: 5 	Validation Loss: 0.653575, Accuracy: 0.785400
Epoch: 6 	Training Loss: 0.375148
Epoch: 6 	Validation Loss: 0.613076, Accuracy: 0.800500
Epoch: 7 	Training Loss: 0.288679
Epoch: 7 	Validation Loss: 0.578173, Accuracy: 0.815700
Epoch: 8 	Training Loss: 0.223138
Epoch: 8 	Validation Loss: 0.612127, Accuracy: 0.816600
Epoch: 9 	Training Loss: 0.164166
Epoch: 9 	Validation Loss: 0.739807, Accuracy: 0.810900
Epoch: 10 	Training Loss: 0.131383
Epoch: 10 	Validation Loss: 0.744424, Accuracy: 0.805900
Epoch: 11 	Training Loss: 0.106864
Epoch: 11 	Validation Loss: 0.753105, Accuracy: 0.807700
Epoch: 12 	Training Loss: 0.091889
Epoch: 12 	Validation Loss: 0.812906, Accuracy: 0.821200
Epoch: 13 	Training Loss: 0.085401
Epoch: 13 	Validation Loss: 0.910178, Accuracy: 0.804900
Epoch: 14 	Training Loss: 0.077790
Epoch: 14 	Validation Loss: 0.822104, Accuracy: 0.817300
Epoch: 15 	Training Loss: 0.064528
Epoch: 15 	Validation Loss: 0.857640, Accuracy: 0.809500
Epoch: 16 	Training Loss: 0.064127
Epoch: 16 	Validation Loss: 0.981881, Accuracy: 0.815400
Epoch: 17 	Training Loss: 0.060451
Epoch: 17 	Validation Loss: 0.912227, Accuracy: 0.818700
Epoch: 18 	Training Loss: 0.056092
Epoch: 18 	Validation Loss: 0.971301, Accuracy: 0.818500
Epoch: 19 	Training Loss: 0.052511
Epoch: 19 	Validation Loss: 1.054556, Accuracy: 0.803700
Epoch: 20 	Training Loss: 0.052957
Epoch: 20 	Validation Loss: 0.989012, Accuracy: 0.818500

参考

  • https://zhuanlan.zhihu.com/p/76421850

  • https://github.com/deep-diver/AlexNet

  • http://noahsnail.com/2017/07/18/2017-07-18-AlexNet%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91%E2%80%94%E2%80%94%E4%B8%AD%E6%96%87%E7%89%88/

  • https://towardsdatascience.com/implementing-alexnet-cnn-architecture-using-tensorflow-2-0-and-keras-2113e090ad98

  • https://blog.csdn.net/weixin_26752765/article/details/108133073

  • https://blog.csdn.net/weixin_42201701/article/details/98098281

  • https://blog.csdn.net/Powerking666/article/details/120709108

  • https://datahacker.rs/tf-alexnet/

  • https://www.tensorflow.org/api_docs/python/tf/data/Dataset

  • https://zh.wikipedia.org/wiki/AlexNet

  • https://zhuanlan.zhihu.com/p/42914388

  • https://zh.wikipedia.org/wiki/ImageNet

你可能感兴趣的:(图像分类,cnn,alexnet,keras,tensorflow,relu)