阅读论文(1)AlexNet:ImageNet classification with deep convolutional neural networks
Alexnet卷积神经网络模型
重叠池化(overlapping pooling)
传统不重叠的池化层,步长s与窗口尺寸z是相同的,s = z。而重叠池化步长s小于窗口尺寸z,s < z。
局部响应归一化
参考:https://zhuanlan.zhihu.com/p/434773836
https://blog.csdn.net/yangdashi888/article/details/77918311
Local Response Normalization,LRN
LRN是在卷积和池化后进行的操作,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力
LRN在之后很少使用,被更为优秀的BN(batch normalization)取代了
论文中Alex net使用的LRN参数为k = 2, n = 5, α = 10-4, and β = 0.75
架构
总体架构
architecture,共8层,5层卷积加3层池化
模型在channel维度上分成两部分是为了使用两块GPU 并行运算,论文中使用的GTX 580 3GB memory
注:
- 输入图片为227x227x3,上图中有误
- 图中卷积层数据是经过卷积的输出结果,省略了池化层
分析
对其模型进行分析如下
纠正:前两个卷积层激活之后先是局部响应归一化(LRN)然后才是最大池化,下图中表示有误
以第一个卷积层为例进行分析,其余各卷积层分析同理
输入图片:227x227x3
conv1:96个卷积核,f = 11x11, s = 4, p = 0,根据公式计算得经过conv1卷积输出:55x55x96
maxpool1:f = 3x3, s = 2(重叠池化),同样根据上述公式经过maxpool1池化输出:27x27x96
防止过拟合的策略
数据增强
Data Augmentation,将原始数据进行变换处理,相当于扩充了训练集,具体分为两种方式
- 将图片进行平移、反转变换,或者只取图片的部分(训练输入图片大小不变)
- 改变图片的RGB
Dropout
相当于一个L2正则项,在隐藏层中间加入噪声,提高模型鲁棒性,用来降低过拟合的。在前向传播过程中,前一个层计算并激活之后,进行一次dropout处理,以 p 的概率将输出置为0,具体公式如下
此公式保证了h'的期望仍为h
另一种理解:dropout的巧妙之处在于,相当于在一个模型的训练过程中,综合考虑了多个模型,对于每一个输入,都是不同的神经网络模型。后来又有论文解释这种理解是不合适的,仅仅把dropout当作是一个正则项就好了。
注意
- 只在训练过程中使用
- 应用在多层前馈神经网络隐藏层输出上(多层感知机),也就是cnn中的全连接层
- 丢弃法将输出项随机置为0来控制模型复杂性
- 丢弃概率p为控制模型复杂性的超参数
模型复现
使用pytorch复现Alexnet
数据集
ImageNet:15000000个高分辨率图像,属于22000个类别
ILSVRC:ImageNet Large-Scale Visual Recognition Challenge,该竞赛使用ImageNet数据集的子集,每个类别1000个图像
神经网络搭建
注意:
- 非线性处理紧跟在卷积层之后
- 局部响应归一化LRN跟在非线性处理后,再然后是最大池化,LRN已经不用了(BN替代),可以不用理解学习
from torch import nn
import torch
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 96, kernel_size=11, stride=4), nn.ReLU(),
nn.LocalResponseNorm(size=5, k=2),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(96, 256, kernel_size=5, stride=1, padding=2), nn.ReLU(),
nn.LocalResponseNorm(size=5, k=2),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(256, 384, kernel_size=3, stride=1, padding=1), nn.ReLU(),
nn.Conv2d(384, 384, kernel_size=3, stride=1, padding=1), nn.ReLU(),
nn.Conv2d(384, 256, kernel_size=3, stride=1, padding=1), nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Flatten(),
nn.Linear(9216, 4096), nn.ReLU(), nn.Dropout2d(p=0.5),
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout2d(p=0.5),
nn.Linear(4096, 1000)
)
def forward(self, x):
x = self.model(x)
return x