1、摘要
我将从alexnet的基础原理到具体的代码的实现两个部分进行讲解。代码部分是用pytorch实现的。(也建议初学者使用它,因为官网上下载配置比tensorflow简单很多),在代码部分我会从环境搭建开始讲解,方便小白实现(因为我初学深度学习的时候也是什么都不懂,环境安装就一直出错,哎。。。。希望我踩过的坑大家不要再踩吧)。在了解了这个网络的搭建过程之后,再去学习其他网络,就会比较容易入手了。再详细讲解了Alexnet之后,后续可能会在讲解一下VGG和Googlenet的实现。
2、Alexnet理论讲解
1)历史背景:
Alexnet不是第一个卷积神经网络,在它之前,还有LeNet。但是在LeNet出现后的十几年里,在目标识别领域卷积神经网络一直被传统目标识别算法(特征提取+分类器)所压制,直到2012年AlexNet在ImageNet挑战赛一举夺魁,才使得卷积神经网络再次引起人们的重视。由于Alexnet的稳定性好的特点,现在仍旧被大量的应用于工业领域,而且它只有一个主线程,结构简单,对于初学者,很容易理解入门,所以学习它还是很有意义的。
2)理论讲解:
图1 alexnet网络结构图
Alexnet由八层网络构成,其中包括5层卷积层和3层全连接层。卷积层包含了卷积、激活、池化、局部归一化几个过程,全连接层包括了droupout、激活、全连接几个过程。
图1所示是当年作者论文中的截图,刚开始愣是没看懂,有些小白可能和我一样也不太看得明白,我就按自己的理解给大家讲讲,有什么问题再一起讨论交流哇。
当年由于计算能力比较拉跨,所以作者采用的是两块儿GPU进行训练,图1就是上下两个GPU训练的过程,(该图省略了池化层),第一个长方体是我们224*224*3的一个RGB图片,将这个图片作为第一个卷积层的输入:
conv1:
经过第一次卷积 [kernel_size=11*11,stride=4,channel=3,num=96:卷积核(滤波器)大小为11*11,卷积核通道数为3==上一层输入的通道数,卷积核数目:96] 后得到55*55*96的特征图片,
96==特征图的通道数==上面卷积核的个数
55是通过公式: output=(input-kernel_size+2*padding)/stride+1 ((224-11+2*0)/4+1≈55(向上取整)) 计算而来的。
卷积完之后紧接着一个激活函数relu函数f(x)=max(0,x)进行激活,提高模型的非线性。因为卷积是一个线性的过程,无论进行多少次,都是线性的结果,只有加入非线性激活函数才能提高它的非线性。它比sigmoid函数(f(x)=1/1+e^(-2))用得更广泛一些,有很多的优点,有兴趣的乖乖们可以自己查一下,资料也很多,我就写一些最明显的好处吧。
百度文库对于激活函数的解释是:所谓激活函数(Activation Function),就是在人工神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端。不是很好理解,反正知道它的目的是增加神经网络模型的非线性就行了。
图2 relu函数
图3 sigmoid函数
图4 sigmoid函数与relu函数的导数图
Relu VS Sigmoid:
Sigmoid和Relu激活函数的对比_sigmoid函数和relu函数区别-CSDN博客
1. 防止梯度弥散:
sigmoid的导数只有在0附近的时候有比较好的激活性,在正负饱和区的梯度都接近于0,所以这会造成梯度弥散;而relu函数在大于0的部分梯度为常数,所以不会产生梯度弥散现象。
2. 稀疏激活性:
relu函数在负半区的导数为0,所以一旦神经元激活值进入负半区,那么梯度就会为0,也就是说这个神经元不会经历训练,即所谓的稀疏性。
3. 加快计算:
根据它们的计算公式可以看出sigmoid函数是一个指数函数,比relu函数计算更加复杂。
激活函数斌不会改变模型的参数,所以激活完给到池化层的输入还是55*55*96的特征图(当时作者分两个GPU训练,所以图1展示的是96通道分成两半,一个GPU跑48个通道)。池化层(kernel_size=3*3,stride=2,根据上面卷积层的公式可以推出:经过池化层后的特征图为:(55-3)/2+1=27)27*27*96(96是因为池化层不改变深度)
池化层的官方解释是:在卷积神经网络中通常会在相邻的卷积层之间加入一个池化层,池化层可以有效的缩小参数矩阵的尺寸,从而减少最后全连接层的中的参数数量。
通俗来说池化层的作用就是 :改变图片的长和宽,不改变其通道数。因为池化层没有参数,不需要用反向传播来改变它的值,减轻了网络的计算量。池化的方法主要有平均池化和最大池化。alexnet采用的是最大池化的方法。
Max Pooling:选取最大的,我们定义一个空间邻域(比如,2*2的窗口),并从窗口内的修正特征图中取出最大的元素,最大池化被证明效果更好一些。
Average Pooling:平均的,我们定义一个空间邻域(比如,2*2的窗口),并从窗口内的修正特征图中算出平均值。
图5 最大池化示意图
池化完了之后还有一个局部归一化(LRN层)的操作:归一化有助于快速收敛;对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
conv2(第二个卷积层)和第一个卷积层的步骤是一样的,只是参数值不同:卷积核用的是5*5的,pad=2,256个kernels。具体的结构和参数下图6解释的比较清楚,要是还是不明白可以私我,给你讲讲,🤭。
图6 Alexnet 网络结构图
具体的参数计算如下:(忘了从哪儿看到的了,就先不附上链接了)
Alexnet网络参数的数目:
卷积层:
weights=K^2xCxN--------------------k:卷积核的大小 ,C:前一层输入图片的通道数,N:卷积核的个 数
biases=N---------------------------------N:卷积核的个数
Parameters=biases+weight
全连接层:
weights= K^2xNxNF------------------K:前一层的输出图片尺寸,N:前一层卷积核数量,NF:全连接 神经元数量
biases=NF-------------------------------NF:全连接层神经元数量
eg:conv1:
卷积层:
weights=11x11x3x96=34848
biases=96
parameters=34848+96=34944
全连接层:
weights=6x6x256x4096=37748736
biases=4096
parameters=37748736+4096=37752832
自己画了一个网络的流程框图,美丽的翠绿色(本来是用的黄色的,被师兄质疑了我的审美,哎。。。可能是个假女生,最后换成绿色啦,好像还是怪怪的,哈哈哈),🤭🤭。
Alexnet相较于Lenet优点:
1、数据增强: 使用数据增强的方法缓解过拟合现象。 常用的数据增强的算法有:水平翻转图像、随机裁剪、平移变换、颜色变换、光照变换等。
2、使用了GPU加速计算: 使用了gpu加速神经网络的训练。
3、重叠的最大池化层: 在以前的CNN中普遍使用平均池化层,AlexNet全部使用最大池化层,避免了平均池化层的模糊化的效果,并且步长比池化的核的尺寸小,这样池化层的输出之间有重叠,提升了特征的丰富性.
4、Dropout随机失活: 随机忽略一些神经元,以避免过拟合。
5、AlexNet使用ReLU代替了Sigmoid: 其能更快的训练,同时解决sigmoid在训练较深的网络中出现的梯度消失,或者说梯度弥散的问题。 sigmoid的导数只有在0附近的时候有比较好的激活性,在正负饱和区的梯度都接近于0,所以这会造成梯度弥散;而relu函数在大于0的部分梯度为常数,所以不会产生梯度弥散现象。 relu函数在负半区的导数为0,所以一旦神经元激活值进入负半区,那么梯度就会为0,也就是说这个神经元不会经历训练,即所谓的稀疏性。
下面的几个问题大家可以思考一下,反正是我在学习过程中当时没太明白的地方,不清楚的可以和我交流哦。
1、输入数据的大小可以改变吗?
2、为什么卷积核大小一般都是奇数*奇数呢?
3、卷积层的卷积到底是怎么进行的呢?
4、是不是小卷积核一定比大卷积核更好呢?
5、为什么卷积层的参数会比全连接层少很多呢?