作者:pierce2502910693 | 来源:互联网 | 2023-09-02 19:26
深度学习图像分类(二):AlexNet
文章目录 深度学习图像分类(二):AlexNet 前言 一、AlexNet理论 1. 激活函数:ReLU 2. 随机失活:Dropout 3. 数据扩充:Data augmentation 4. 多GPU实现 5. 局部响应归一化(LRN) 二、 AlexNet代码 小结
前言 2012年,Alex Krizhevsky、Ilya Sutskever在多伦多大学Geoff Hinton的实验室设计出了一个深层的卷积神经网络AlexNet,夺得了2012年ImageNet LSVRC的冠军,且准确率远超第二名(top5错误率为15.3%,第二名为26.2%),引起了很大的轰动。AlexNet可以说是具有历史意义的一个网络结构,在此之前,深度学习已经沉寂了很长时间,自2012年AlexNet诞生之后,后面的ImageNet冠军都是用卷积神经网络(CNN)来做的,并且层次越来越深,使得CNN成为在图像识别分类的核心算法模型,带来了深度学习的大爆发。 小tips: Alex并没有给自己的网络起名字,所以后人为了方便将这个网络成为AlexNet。同学们如果不想让别人给自己的网络起名字,写论文的时候记得起个名字~
一、AlexNet理论 AlexNet其实跟LeNet很像很像,几乎可以说是LeNet的升级版,都是有卷积和全连接组成。AlexNet之所以能够成功,跟这个模型设计的特点有关,主要有:
使用了非线性激活函数:ReLU 随机失活:Dropout 数据扩充:Data augmentation 其他:多GPU实现,LRN归一化层的使用 1. 激活函数:ReLU 传统的神经网络普遍使用Sigmoid或者tanh等非线性函数作为激励函数,然而它们容易出现梯度弥散或梯度饱和的情况。以Sigmoid函数为例,如下图所示,当输入的值非常大或者非常小的时候,这些神经元的梯度接近于0(梯度饱和现象),如果输入的初始值很大的话,梯度在反向传播时因为需要乘上一个Sigmoid导数,会造成梯度越来越小,导致网络变的很难学习。 relu函数直到现在也是学术界和工业界公认的最好用的激活函数之一,在各个不同领域不同模型下的使用非常之多 。
2. 随机失活:Dropout 引入Dropout主要是为了防止网络在训练过程中由于参数冗余出现的过拟合现象。在神经网络中Dropout通过修改神经网络本身结构来实现,对于某一层的神经元,通过定义的概率将神经元置为0,这个神经元就不参与前向和后向传播,就如同在网络中被删除了一样,同时保持输入层与输出层神经元的个数不变,然后按照神经网络的学习方法进行参数更新。在下一次迭代中,又重新随机删除一些神经元(置为0),直至训练结束。
3. 数据扩充:Data augmentation 由于神经网络算法是基于数据驱动的,因此,有一种观点认为神经网络是靠数据喂出来的,如果能够增加训练数据,提供海量数据进行训练,则能够有效提升算法的准确率,因为这样可以避免过拟合,从而可以进一步增大、加深网络结构。而当训练数据有限时,可以通过一些变换从已有的训练数据集中生成一些新的数据,以快速地扩充训练数据。 其中,最简单、通用的图像数据变形的方式:水平翻转图像,从原始图像中随机裁剪、平移变换,颜色、光照变换,如下图所示: 数据增广确实是提升模型的有效手段,而且最近的增广方式也不仅限于这种随即裁剪,也可以使用生成对抗网络进行图像生成来达到图像增广的目的 。
4. 多GPU实现 AlexNet当时使用了GTX580的GPU进行训练,由于单个GTX 580 GPU只有3GB内存,这限制了在其上训练的网络的最大规模,因此他们在每个GPU中放置一半核(或神经元),将网络分布在两个GPU上进行并行计算,大大加快了AlexNet的训练速度。
5. 局部响应归一化(LRN) Local Response Normalization(LRN)技术主要是深度学习训练时的一种提高准确度的技术方法。LRN一般是在激活、池化后进行的一种处理方法。LRN归一化技术首次在AlexNet模型中提出这个概念。通过实验确实证明它可以提高模型的泛化能力,但是提升的很少,以至于后面不再使用,甚至有人觉得它是一个“伪命题”,因而它饱受争议。现在基本上已经被Batch Normalization代替 。
因此,这里简单介绍一下: 局部归一化的灵感来源 在神经生物学中,有一个概念叫做侧抑制(lateral inhibitio ),指的是被激活的神经元会抑制它周围的神经元,而归一化(normalization)的的目的不就是“抑制”吗,两者不谋而合,这就是局部归一化的动机,它就是借鉴“侧抑制”的思想来实现局部抑制,当我们使用RELU损失函数的时候,这种局部抑制显得很有效果。
归一化的好处 (1)为了后面数据处理的方便,归一化的确可以避免一些不必要的数值问题。 (2)为了程序运行时收敛加快。 (3)同一量纲。样本数据的评价标准不一样,需要对其量纲化,统一评价标准。这算是应用层面的需求。 (4)避免神经元饱和。就是当神经元的激活在接近0或者1时会饱和,在这些区域,梯度几乎为0,这样,在反向传播过程中,局部梯度就会接近0,这会有效地“杀死”梯度。 (5)保证输出数据中数值小的不被吞食。
实验总结 由于LRN模仿生物神经系统的侧抑制机制,对局部神经元的活动创建竞争机制,使得响应比较大的值会更大,提高了模型的泛化能力,Hinton在ImageNet中的实验准确率分别提升了1.4%和1.2%。
二、 AlexNet代码 这里给出模型搭建的python代码(基于pytorch实现)。完整的代码是基于图像分类问题的(包括训练和推理脚本,自定义层等)详见我的GitHub: 完整代码链接 ps:里面还有其他经典模型的代码复现,希望对大家有用
from turtle import forwardimport torchimport torch. nn as nnfrom custom_layers. CustomLayers import ConvActivationclass AlexNet ( nn. Module) : def __init__ ( self, num_classes, input_channels= 3 , init_weights = True ) : super ( ) . __init__( ) self. features = nn. Sequential( ConvActivation( input_channels= input_channels, output_channels= 48 , kernel_size= 11 , stride= 4 , padding= 2 ) , nn. MaxPool2d( kernel_size= 3 , stride= 2 ) , ConvActivation( input_channels= 48 , output_channels= 128 , kernel_size= 5 , padding= 2 ) , nn. MaxPool2d( kernel_size= 3 , stride= 2 ) , ConvActivation( input_channels= 128 , output_channels= 192 , kernel_size= 3 , padding= 1 ) , ConvActivation( input_channels= 192 , output_channels= 192 , kernel_size= 3 , padding= 1 ) , ConvActivation( input_channels= 192 , output_channels= 128 , kernel_size= 3 , padding= 1 ) , nn. MaxPool2d( kernel_size= 3 , stride= 2 ) ) self. classifier = nn. Sequential( nn. Dropout( p= 0.5 ) , nn. Linear( 128 * 6 * 6 , 2048 ) , nn. ReLU( True ) , nn. Dropout( p= 0.4 ) , nn. Linear( 2048 , 2048 ) , nn. ReLU( True ) , nn. Linear( 2048 , num_classes) ) if init_weights: self. _initialize_weights( ) def _initialize_weights ( self) : for m in self. modules( ) : if isinstance ( m, nn. Conv2d) : nn. init. kaiming_normal_( m. weight, mode= 'fan_out' , nonlinearity= 'relu' ) if m. bias is not None : nn. init. constant_( m. bias, 0 ) elif isinstance ( m, nn. Linear) : nn. init. normal_( m. weight, 0 , 0.01 ) nn. init. constant_( m. bias, 0 ) def forward ( self, x) : assert x. shape[ 2 ] == 224 and x. shape[ 3 ] == 224 , " input images size should be 224*224 " x = self. features( x) x = torch. flatten( x, start_dim= 1 ) x = self. classifier( x) return x
小结 AelxNet可以说掀起了人工智能的第三次浪潮:深度学习的时代。其历史影响深远。 虽然里面的技术在现在看来没什么创新点,但是放在当时,其性能也甩了其他算法好几条街。