AlexNet在2012年ImageNet竞赛中以超过第二名10.9个百分点的绝对优势一举夺冠,从此深度学习和卷积神经网络名声鹊起,深度学习的研究如雨后春笋般出现,AlexNet的出现可谓是卷积神经网络的王者归来。
闪光点:
- 更深的网络
- 数据增广
- ReLU
- dropout
- LRN
以上图AlexNet架构为例,这个网络前面5层是卷积层,后面三层是全连接层,最终softmax输出是1000类,取其前两层进行详细说明。
-
AlexNet共包含5层卷积层和三层全连接层,层数比LeNet多了不少,但卷积神经网络总的流程并没有变化,只是在深度上加了不少。
-
AlexNet针对的是1000类的分类问题,输入图片规定是256×256的三通道彩色图片,为了增强模型的泛化能力,避免过拟合,作者使用了随机裁剪的思路对原来256×256的图像进行随机裁剪,得到尺寸为3×224×224的图像,输入到网络训练。
-
因为使用多GPU训练,所以可以看到第一层卷积层后有两个完全一样的分支,以加速训练。
- 针对一个分支分析:第一层卷积层conv1的卷积核尺寸为11×11,滑动步长为4,卷积核数目为48。卷积后得到的输出矩阵为[48,55,55]。这里的55是个难以理解的数字,作者也没有对此说明,如果按照正常计算的话(224-11)/4+1 != 55的,所以这里是做了padding再做卷积的,即先padiing图像至227×227,再做卷积(227-11)/4+1 = 55。这些像素层经过relu1单元的处理,生成激活像素层,尺寸仍为2组48×55×55的像素层数据
。然后经过归一化处理,归一化运算的尺度为5*5。第一卷积层运算结束后形成的像素层的规模为48×27×27。 -
输入矩阵是[48,55,55].接着是池化层,做max pooling操作,池化运算的尺度为3*3,运算的步长为2,则池化后图像的尺寸为(55-3)/2+1=27。所以得到的输出矩阵是[48,27,27]。后面层不再重复叙述。
AlexNet用到训练技巧:
- 数据增广技巧来增加模型泛化能力。
- 用ReLU代替Sigmoid来加快SGD的收敛速度
- Dropout:Dropout原理类似于浅层学习算法的中集成算法,该方法通过让全连接层的神经元(该模型在前两个全连接层引入Dropout)以一定的概率失去活性(比如0.5)失活的神经元不再参与前向和反向传播,相当于约有一半的神经元不再起作用。在测试的时候,让所有神经元的输出乘0.5。Dropout的引用,有效缓解了模型的过拟合。
- Local Responce Normalization:局部响应归一层的基本思路是,假如这是网络的一块,比如是 13×13×256, LRN 要做的就是选取一个位置,比如说这样一个位置,从这个位置穿过整个通道,能得到 256 个数字,并进行归一化。进行局部响应归一化的动机是,对于这张 13×13 的图像中的每个位置来说,我们可能并不需要太多的高激活神经元。但是后来,很多研究者发现 LRN 起不到太大作用,因为并不重要,而且我们现在并不用 LRN 来训练网络。
AlexNet的Keras实现:
def AlexNet():
model = Sequential()
model.add(Conv2D(96,(11,11),strides=(4,4),input_shape=(227,227,3),padding='valid',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))
model.add(Conv2D(256,(5,5),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))
model.add(Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(MaxPooling2D(pool_size=(3,3),strides=(2,2)))
model.add(Flatten())
model.add(Dense(4096,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000,activation='softmax'))
return model