AlexNet.pdf

AlexNet中文翻译 .docx

5.第二篇论文AlexNet——第二课时2.1.mp4 .mp4_20201020_163059.382.png
AlexNet - 图3

简介

数据集

在 ImageNet LSVRC-2010 数据集上的 120万张图片上进行分类(类别数为1000)

错误率

  • top-1 :37.5%
  • top-5 :17.0% (Top5错误率:神经网络认为最可能的5个类别都错误)

    参数

  • 6000万参数

  • 65万个神经元

    重要技术

  • ReLU

  • Dropout

主要架构 Architecture

非线性激活函数——ReLU

常用的激活函数有:
AlexNet - 图4
AlexNet - 图5
但作者认为 ReLU 函数可以使得神经网络更快的收敛,这在大型网络的训练中非常重要。
image.png
这是4层卷积神经网络在 CIFAR-10 数据集上的训练过程,使神经网络的错误率从75%降到25%.
实线部分是用 ReLU 激活函数,虚线部分是用 tanh 函数,可以看到 ReLU 比 tanh 收敛快了接近6倍。

优点:

  1. 使网络训练更快(一方面是反向传播时梯度计算更简单)
  2. 防止梯度消失/梯度爆炸
  3. 使网络具有稀疏性

image.png

Dropout

image.png

当训练一个深度神经网络时,我们可以随机丢弃一部分神经元(同时丢弃其对应的连接边)来避免过拟合,这种方法称为丢弃法( Dropout Method ).
花书中认为dropout可以看做一种Bagging方法,例如对以下有4个节点的Base network做dropout,就相当于2^4个subnetwork的ensemble.
image.png

在多GPU上训练

该神经网络是在2块GTX 580 GPU上训练的,由于 GTX 580 的显存只有 3GB,无法储存这么多参数,因此作者将神经网络设计成相同的两部分,在两块GPU上分别训练,如下图所示,一个GPU训练上面的神经网络,另一个GPU训练下面的,两个GPU仅在某些层间(第3个卷积层和后面所有的全连接层)进行数据互传。
作者做过实验,双GPU比单GPU的 top-1 和 top-5 错误率分别下降了 1.7% 和1.2%.

p1.png

局部响应归一化 Local Response Normalization

image.png
这是一个将数据归一化的方法,大意就是将相邻的n个神经元来做归一化。
但现在的深度网络中很少用到了,一般都是用批归一化(Batch Normalization)或组归一化(Group Normalization),因此就不详细介绍了。

重叠池化 Overlapping Pooling

重叠池化的步幅比池化窗口的长宽都要小,会导致池化感受野和上一步的感受野有重叠的地方,例如文中的池化窗口大小为3x3,但步幅为2,就会产生1个像素的重叠。
作者发现使用重叠池化有助于防止过拟合。

神经网络整体架构

AlexNet - 图12

AlexNet - 图13

  • 输入层( input ):输入的图片的size为 AlexNet - 图14
  • 卷积层(Conv1):有48*2=96个卷积核,大小为 AlexNet - 图15 ,步幅stride=4,零填充Padding=3
  • 池化层( Pool1 ) :Max Pooling 窗口大小为 AlexNet - 图16,stride=2
  • 卷积层(Conv2):有128*2=256个卷积核,大小为 AlexNet - 图17 ,stride=1,Padding=2
  • 池化层( Pool2 ) :Max Pooling 窗口大小为 AlexNet - 图18,stride=2
  • 卷积层(Conv3):有192*2=384个卷积核,大小为 AlexNet - 图19 ,stride=1,Padding=1
  • 卷积层(Conv4):有192*2=384个卷积核,大小为 AlexNet - 图20 ,stride=1,Padding=1
  • 卷积层(Conv5):有128*2=256个卷积核,大小为 AlexNet - 图21 ,stride=1,Padding=1
  • 池化层( Pool5 ) :Max Pooling 窗口大小为 AlexNet - 图22,stride=2
  • 全连接层(FC1):有2*2048个神经元
  • 全连接层(FC2):有2*2048个神经元
  • 全连接层(FC3):有1000个神经元
  • Softmax输出层:输出1000个类别的概率

此外, AlexNet 还在Pool1,Pool2 两个池化层之后进行了局部响应归一化( Local Response Normalization, LRN )以增强模型的泛化能力.

输出特征图大小计算公式为:
AlexNet - 图23

  • Conv1的特征图尺寸为 AlexNet - 图24,特征图大小为55x55x96
  • Pool1的特征图尺寸为 AlexNet - 图25,特征图大小为27x27x96
  • Conv2的特征图尺寸为 AlexNet - 图26,特征图大小为27x27x256
  • Pool2 的特征图尺寸为 AlexNet - 图27,特征图大小为13x13x256
  • Conv3的特征图尺寸为 AlexNet - 图28,特征图大小为13x13x384
  • Conv4的特征图尺寸为 AlexNet - 图29,特征图大小为13x13x384
  • Conv4的特征图尺寸为 AlexNet - 图30,特征图大小为13x13x256
  • Pool5 的特征图尺寸为 AlexNet - 图31,特征图大小为6x6x256

image.png

AlexNet.xlsx
6.第二篇论文AlexNet——第二课时2.2.mp4 .mp4_20201020_165720.901.png

Pytorch 实现

参考:https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py

  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. class Net(nn.Module):
  5. def __init__(self):
  6. super(Net, self).__init__()
  7. self.conv1 = nn.Conv2d(
  8. in_channels=3, out_channels=96, kernel_size=(11, 11), stride=4, padding=3)
  9. self.pool1 = nn.MaxPool2d(kernel_size=(3, 3), stride=2)
  10. self.conv2 = nn.Conv2d(96, 256, (5, 5), 1, 2)
  11. self.pool2 = nn.MaxPool2d(kernel_size=(3, 3), stride=2)
  12. self.conv3 = nn.Conv2d(256, 384, (3, 3), 1, 1)
  13. self.conv4 = nn.Conv2d(384, 384, (3, 3), 1, 1)
  14. self.conv5 = nn.Conv2d(384, 256, (3, 3), 1, 1)
  15. self.pool5 = nn.MaxPool2d(kernel_size=(3, 3), stride=2)
  16. self.drop = nn.Dropout(0.5)
  17. self.fc1 = nn.Linear(6*6*256, 4096)
  18. self.fc2 = nn.Linear(4096, 4096)
  19. self.fc3 = nn.Linear(4096, 1000)
  20. def forward(self, x):
  21. x = self.pool1(F.relu(self.conv1(x)))
  22. x = self.pool2(F.relu(self.conv2(x)))
  23. x = F.relu(self.conv3(x))
  24. x = F.relu(self.conv4(x))
  25. x = self.pool5(F.relu(self.conv5(x)))
  26. # 将 x 转化成向量
  27. x = x.view(-1, self.num_flat_features(x))
  28. x = self.drop(F.relu(self.fc1(x)))
  29. x = self.drop(F.relu(self.fc2(x)))
  30. x = self.fc3(x)
  31. return x
  32. def num_flat_features(self, x):
  33. size = x.size()[1:] # all dimensions except the batch dimension
  34. num_features = 1
  35. for s in size:
  36. num_features *= s
  37. return num_features
  38. net = Net()
  39. print(net)

还有一种用 nn.Sequential 的方法:

  1. import torch.nn as nn
  2. class AlexNet(nn.Module):
  3. def __init__(self, num_classes=1000):
  4. super(AlexNet, self).__init__()
  5. self.features = nn.Sequential(
  6. nn.Conv2d(3, 96, (11, 11), 4, 3),
  7. nn.ReLU(inplace=True),
  8. nn.MaxPool2d(kernel_size=3, stride=2),
  9. nn.Conv2d(96, 256, (5, 5), 1, 2),
  10. nn.ReLU(inplace=True),
  11. nn.MaxPool2d(kernel_size=3, stride=2),
  12. nn.Conv2d(256, 384, (3, 3), 1, 1),
  13. nn.ReLU(inplace=True),
  14. nn.Conv2d(384, 384, (3, 3), 1, 1),
  15. nn.ReLU(inplace=True),
  16. nn.Conv2d(384, 256, (3, 3), 1, 1),
  17. nn.ReLU(inplace=True),
  18. nn.MaxPool2d(kernel_size=3, stride=2),
  19. )
  20. self.classifier = nn.Sequential(
  21. nn.Linear(6*6*256, 4096),
  22. nn.ReLU(inplace=True),
  23. nn.Linear(4096, 4096),
  24. nn.ReLU(inplace=True),
  25. nn.Linear(4096, num_classes),
  26. )
  27. def forward(self, x):
  28. x = self.features(x)
  29. x = x.view(x.size(0), 256 * 6 * 6)
  30. x = self.classifier(x)
  31. return x
  32. if __name__ == '__main__':
  33. # Example
  34. net = AlexNet()
  35. print(net)