AlexNet

在2012年的Imagenet竞赛中,AlexNet以低于第二名10.8个百分点的top-5错误率赢得了冠军,自此以后,基于CNN的图像分类算法开始流行起来,深度学习时代到来了。

Alt text

AlexNet的网络结构如上图所示。相比于之前的LeNet-5,AlexNet堆叠了更多的卷积块,从而网络更深。同时,它还引入了Dropout的技巧,以及ReLU激活函数等。

在AlexNet刚被提出时,受限于当时的算力,作者采用了多个GPU进行训练。而随着技术的发展,现在的算力已经可以在单卡上训练AlexNet了,且显存绰绰有余。

更多细节,将在代码实现中体现。

PyTorch 实现AlexNet

代码实现时,去除了现在已经很少被使用的LRN(局部响应归一化);并且将最后一个池化层由最大池化改为自适应平均池化,这种池化方法可以将不同尺寸的输入图片固定到特定尺寸,于是就可以固定住该池化层后面紧挨着的第一个全连接层的参数(最后一个池化层到第一个全连接之间有一个flatten操作,由于池化层输出的尺寸是固定的,因此flatten后再输入到这个全连接层的神经元个数也是固定的),使用起来更加方便。

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
34
35
36
37
38
39
40
41
import torch
import torch.nn as nn

class AlexNet(nn.Module):

def __init__(self, num_classes: int = 1000) -> None:
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.Flatten(start_dim=1),
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: torch.Tensor) -> torch.Tensor:
x = self.features(x)
x = self.avgpool(x)
x = self.classifier(x)
return x

测试一下:
Alt text

可以看到,对于输入的3*224*224的图片,经过AlexNet后,得到了1000维的向量。

那这中间的shape变化情况是怎么样的呢?我们可以看一下:

1
2
3
4
5
6
7
8
all_layers=nn.ModuleList()
all_layers.extend(model.features)
all_layers.append(model.avgpool)
all_layers.extend(model.classifier)
x=torch.randn(4,3,224,224)
for layer in all_layers:
x=layer(x)
print('\nshape: '+str(x.shape)+' #### layer:',layer)

输出信息便是shape每经过一层后的变化情况,如下:
Alt text

参考: