AlexNet 网络复现

AlexNet 网络复现

参数总量(复现版) 6616714

原版AlexNet用于ImageNet2012数据集的分类预测。但是ImageNet是一个巨大的数据集(132GB),同时在最新的Pytorch当中也不提供下载了,所以便于练习,这里复现使用了CIFAR10这个小型数据集,同时因为图片尺寸不同,对网络也进行了相应的调整。

论文链接

http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf

AlexNet与LeNet有何不同?

主要差异在以下四点:

  1. 卷积网络更深(3 层 -> 5层)
  2. 使用了Local Response Normalization (LRN) 防止过拟合
    • 后来VGG的论文中提到这个LRN实际上没什么卵用。
  3. 用MaxPool取代AvgPool。
    • 效果拔群,我自己也在LeNet-5的复现中尝试过, 对预测准度有显著提升
  4. 使用了DropOut这个防止过拟合的trick

除此以外AlexNet的参数总量是LeNet-5的数十倍。原文

AlexNet原版网络结构

size/operation kernel size Depth stride Stride Padding # Parameters
3 * 227 * 227
Conv1 + ReLU 11 96 4 (11 * 11 * 3 + 1) * 96 = 34944
96 * 55 * 55
Max Pooling 3 2
96 * 27 * 27
Norm
Conv2 + ReLU 5 256 1 2 (5 * 5 * 96 + 1) * 256 = 614656
256 * 27 * 27
Max Pooling 3 2
256 * 13 * 13
Norm
Conv3+ ReLU 3 384 1 1 (3 * 3 * 256 + 1) * 384 = 885120
384 * 13 * 13
Conv4+ ReLU 3 384 1 1 (3 * 3 * 384 + 1) * 384 = 1327488
384 * 13 * 13
Conv3+ ReLU 3 256 1 1 (3 * 3 * 384 + 1) * 256 = 884992
256 * 13 * 13
Max Pooling 3 2
256 * 6 * 6
FC6+ReLU (256 * 6 * 6 ) * 4096 = 37748736
4096
Dropout (rate 0.5)
FC7 + ReLU 4096 * 4096 = 16777216
4096
FC8 + ReLU 4096 * 1000 = 4096000
1000

用于CIFAR10的AlexNet网络结构

  • 主要差异在于:
    • 修改了第一个卷积层的参数 (k, s, p)
      • (11,4,0) -> (7, 2, 2)
    • 修改了FCC层的神经元数量
      • fcc1: 4096 -> 1024
      • fcc2: 4096 -> 512
    • 取消了最后一层卷积层后面的MaxPooling
    • 取消了Dropout
    • 没有使用LRN
size/operation kernel size Depth stride Stride Padding # Parameters
3 * 32 * 32
Conv1 + ReLU 7 96 2 2
96 * 15 * 15
Max Pooling 3 2
96 * 7 * 7
Norm
Conv2 + ReLU 5 256 1 2
256 * 7 * 7
Max Pooling 3 2
256 * 3* 3
Norm
Conv3+ ReLU 3 384 1 1
384 * 3 * 3
Conv4+ ReLU 3 384 1 1
384 * 3 * 3
Conv5+ ReLU (相比于原模型这里少了MaxPool) 3 256 1 1
256 * 3 * 3
FC6+ReLU
1024
FC7 + ReLU
512
FC8 + ReLU
10

一些固定的超参数

batch_size = 64
lr = 0.001
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(...)
Epochs = 10

关键代码

class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()

        self.cnn = nn.Sequential(
            nn.Conv2d(3, 96, 7, 2, 2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(3, 2, 0),
            
            nn.Conv2d(96, 256, 5, 1, 2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(3, 2, 0),

            nn.Conv2d(256, 384, 3, 1, 1),
            nn.ReLU(inplace=True),

            nn.Conv2d(384, 384, 3, 1, 1),
            nn.ReLU(inplace=True),

            nn.Conv2d(384, 256, 3, 1, 1),
            nn.ReLU(inplace=True)
        )

        self.fc = nn.Sequential(
            nn.Linear(256*3*3, 1024),
            nn.Dropout(p = 0.5),
            nn.ReLU(),
            nn.Linear(1024, 512),
            nn.Dropout(p = 0.5),
            nn.ReLU(),
            nn.Linear(512, 10)
        )

    def forward(self, x):
        x = self.cnn(x)

        x = x.view(x.size()[0], -1)
        x = self.fc(x)

        return x

使用的数据集是cifar10(32x32图像)

由于原始的AlexNet是在ImageNet数据集(227x227尺寸)上训练的,因此在cifar10上训练的模型需要进行修改(kernel size和全连接层的节点数量)。

对比AlexNet和LeNet

  • Accuracy
    • AlexNet: 0.6064 (loss = 0.4336)
    • LeNet: 0.5929 (loss = 1.1997)

BatchNorm的效果

一般认为BatchNorm的作用是加速收敛,并不能显著降低过拟合。

  • Accuracy
    • With BatchNorm: 0.4513 (loss = 0.1310) (出现过拟合???)
    • Without BatchNorm: 0.6064 (loss = 0.4336)

Dropout的效果

Dropout 也就是随机丢弃一定比例的神经元,起到防止过拟合的作用。

  • 注意:
    • Pytorch 的dropOut 参数 p 是丢弃神经元的概率不是保留神经元的概率
    • 同时nn.DropOut本身实现了Rescale操作,所以也不需要手动去实现
    • DropOut只在训练时起作用
  • Accuracy
    • With DropOut: 0.6443 (loss = 0.3142) 提升显著
    • Without DropOut: 0.6064 (loss = 0.4336)

你可能感兴趣的:(网络复现笔记,深度学习,神经网络,机器学习,卷积神经网络)