AlexNet:ImageNet classification with deep convolutional neural networks
卷积神经网络从这里开始开始火起来,主要内容包括:(1)使用relu训练网络;(2)使用LRN层;(3)使用数据增强;(4)使用dropout;(5)使用重叠池化
什么是 AlexNet?
- AlexNet是由Alex Krizhevsky 提出的首个应用于图像分类的深层卷积神经网络
- AlexNet和LeNet 很像,基础模块均是:卷积+激活+下采样,但是AlexNet更深
AlexNet的网络结构?
- 训练阶段: 每张训练图片256x256,然后我们随机裁剪出224x224大小的图片,作为CNN的输入进行训练
- 测试阶段: 输入256x256大小的图片,我们从图片的5个指定的方位(上下左右+中间)进行裁剪出5张224x224大小的图片,然后水平镜像一下再裁剪5张,这样总共有10张;然后我们把这10张裁剪图片分别送入已经训练好的CNN中,分别预测结果,最后用这10个结果的平均作为最后的输出
- 8个学习层,包括5个卷积层和3个全连接层,其余层为 局部响应归一化(Local Response Normalization,LRN)层,池化层,softmax 输出层
AlexNet的损失函数?
- AlexNet输入是图片(c,h,w),输出是1000,表示该图片的分类结果
- AlexNet使用交叉熵损失(CrossEntropyLoss) 计算损失
Alexnet中为什么选择使用relu作为激活函数,而不是tanh?
- tanh 是饱和激活函数,而 Relu 是非饱和的,饱和激活函数更难训练网络,非饱和函数可以让梯度传播到更深层的网络中
- 在同等训练效果下,使用relu比tanh训练更快
Alexnet如何使用多GPU进行训练?
- 将每层一半的内核(或神经元)分别放在2个GPU上
- 第三层从第二层的2个GPU获取输入,而第四层从第三层的各自GPU获取输入
- GPU的交叉连接,类似交叉验证,减低了模型过拟合,最终使得分类top-1,top5错误率降低1.7%和1.2%
- AlexNet通过通过分组filter训练模型,类似于分组卷积(Group Convolution) ,之所以能减少过拟合,本质是分组卷积降低了filter之间的依赖,相当于正则化(regularization)模型,详细查看:为什么分组卷积有用
如何理解Alexnet中的重叠池化?
- 重叠池化(Overlapping Pooling)使得Alexnet在ImageNet上的top-1和top-5的错误率分别降低了0.4%和0.3%
- 使用后,过拟合 (overfitting)现象出现减少
AlexNet如何减少过拟合?
- 数据增强:(1)取4角+中心的224*224区域并进行平移及水平翻转,获得10倍数据量;(2)PCA颜色调整: 比如说,如果你的图片呈现紫色,即主要含有红色和蓝色,绿色很少,然后PCA颜色增强算法就会对红色和蓝色增减很多,绿色变化相对少一点,所以使总体的颜色保持一致
- 使用丢弃正则化(Dropout):避免过拟合的同时,也较少模型收敛时间
为什么输入到AlexNet网络的图片必须大小固定?
- 卷积层不管原图或featrue map的大小,不需要固定
- 全连接层因为需要固定输出数量,所以需要固定尺寸输入,导致网络需要固定输入
- 一般在前处理上使用resize或corp的操作,将数据变为固定尺寸输入;也可以使用空间金字塔池化(Spatial Pyramid Pooling,SPP)将不同大小的图片转为一致的尺寸
如何使用 Pytorch 定义 AlexNet?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34class AlexNet(nn.Module):
def __init__(self, num_classes=1000):
super(AlexNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(64, 192, kernel_size=5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(192, 384, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
self.classifier = nn.Sequential(
nn.Dropout(),
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes),
)
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x