AlexNet模型
1. AlexNet模型介绍1.1 AlexNet的特点1.2 AlexNet的结构1.3 AlexNet参数数量2. AlexNet的PyTorch实现2.1 导入相应的包2.2 构建AlexNet网络2.3 加载数据集2.4 训练网络1. AlexNet模型介绍
由于受到计算机性能的影响,虽然LeNet在图像分类中取得了较好的成绩,但是并没有引起很多的关注。 直到,Alex等人提出的AlexNet网络在ImageNet大赛上以远超第二名的成绩夺冠,卷积神经网络乃至深度学习重新引起了广泛的关注。AlexNet首次证明了学习到的特征可以超越⼿⼯设计的特征,从而⼀举打破计算机视觉研究的前状。
1.1 AlexNet的特点
AlexNet是在LeNet的基础上加深了网络的结构,学习更丰富更高维的图像特征。AlexNet的特点:
更深的网络结构使用层叠的卷积层,即卷积层+卷积层+池化层来提取图像的特征使用Dropout抑制过拟合使用数据增强Data Augmentation抑制过拟合使用Relu替换之前的sigmoid的作为激活函数多GPU训练
1.2 AlexNet的结构
AlexNet的结构为:
上图是论文中的原图,比较复杂,不容易看清楚,下图是更清晰的结构图:
网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。
卷积层C1该层的处理流程是: 卷积–>ReLU–>池化–>归一化。卷积,输入是227×227,使用96个11×11×3的卷积核,得到的FeatureMap为55×55×96。ReLU,将卷积层输出的FeatureMap输入到ReLU函数中。池化,使用3×3步长为2的池化单元(重叠池化,步长小于池化单元的宽度),输出为27×27×96((55−3)/2+1=27)局部响应归一化,使用k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为27×27×96,输出分为两组,每组的大小为27×27×48卷积层C2该层的处理流程是:卷积–>ReLU–>池化–>归一化卷积,输入是2组27×27×48。使用2组,每组128个尺寸为5×5×48的卷积核,并作了边缘填充padding=2,卷积的步长为1. 则输出的FeatureMap为2组,每组的大小为27×27 times128. ((27+2∗2−5)/1+1=27)ReLU,将卷积层输出的FeatureMap输入到ReLU函数中池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为(27−3)/2+1=13,输出为13×13×256局部响应归一化,使用k=2,n=5,α=10−4,β=0.75进行局部归一化,输出的仍然为13×13×256,输出分为2组,每组的大小为13×13×128卷积层C3该层的处理流程是: 卷积–>ReLU卷积,输入是13×13×256,使用2组共384尺寸为3×3×256的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times384ReLU,将卷积层输出的FeatureMap输入到ReLU函数中卷积层C4该层的处理流程是: 卷积–>ReLU该层和C3类似。卷积,输入是13×13×384,分为两组,每组为13×13×192.使用2组,每组192个尺寸为3×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13 times384,分为两组,每组为13×13×192ReLU,将卷积层输出的FeatureMap输入到ReLU函数中卷积层C5该层处理流程为:卷积–>ReLU–>池化卷积,输入为13×13×384,分为两组,每组为13×13×192。使用2组,每组为128尺寸为3×3×192的卷积核,做了边缘填充padding=1,卷积的步长为1.则输出的FeatureMap为13×13×256ReLU,将卷积层输出的FeatureMap输入到ReLU函数中池化,池化运算的尺寸为3×3,步长为2,池化后图像的尺寸为 (13−3)/2+1=6,即池化后的输出为6×6×256全连接层FC6该层的流程为:(卷积)全连接 -->ReLU -->Dropout卷积->全连接: 输入为6×6×256,该层有4096个卷积核,每个卷积核的大小为6×6×256。由于卷积核的尺寸刚好与待处理特征图(输入)的尺寸相同,即卷积核中的每个系数只与特征图(输入)尺寸的一个像素值相乘,一一对应,因此,该层被称为全连接层。由于卷积核与特征图的尺寸相同,卷积运算后只有一个值,因此,卷积后的像素层尺寸为4096×1×1,即有4096个神经元。ReLU,这4096个运算结果通过ReLU激活函数生成4096个值Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元全连接层FC7流程为:全连接–>ReLU–>Dropout全连接,输入为4096的向量ReLU,这4096个运算结果通过ReLU激活函数生成4096个值Dropout,抑制过拟合,随机的断开某些神经元的连接或者是不激活某些神经元输出层第七层输出的4096个数据与第八层的1000个神经元进行全连接,经过训练后输出1000个float型的值,这就是预测
1.3 AlexNet参数数量
卷积层的参数 = 卷积核的数量 * 卷积核 + 偏置
C1: 96个11×11×3的卷积核,96×11×11×3+96=34848C2: 2组,每组128个5×5×48的卷积核,(128×5×5×48+128)×2=307456C3: 384个3×3×256的卷积核,3×3×256×384+384=885120C4: 2组,每组192个3×3×192的卷积核,(3×3×192×192+192)×2=663936C5: 2组,每组128个3×3×192的卷积核,(3×3×192×128+128)×2=442624FC6: 4096个6×6×256的卷积核,6×6×256×4096+4096=37752832FC7: 4096∗4096+4096=16781312output: 4096∗1000=4096000
卷积层 C2,C4,C5中的卷积核只和位于同一GPU的上一层的FeatureMap相连。从上面可以看出,参数大多数集中在全连接层,在卷积层由于权值共享,权值参数较少。
2. AlexNet的PyTorch实现
2.1 导入相应的包
import timeimport torchfrom torch import nn, optimimport torchvisionimport numpy as npimport syssys.path.append("/home/kesci/input/") import d2lzh1981 as d2limport osimport torch.nn.functional as F
2.2 构建AlexNet网络
# 如果有GPU,开启GPUdevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')class AlexNet(nn.Module):def __init__(self):super(AlexNet, self).__init__()self.conv = nn.Sequential(# in_channels, out_channels, kernel_size, stride, paddingnn.Conv2d(1, 96, 11, 4),nn.ReLU(),# kernel_size, stridenn.MaxPool2d(3, 2), # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数nn.Conv2d(96, 256, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(3, 2),# 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。# 前两个卷积层后不使用池化层来减小输入的高和宽nn.Conv2d(256, 384, 3, 1, 1),nn.ReLU(),nn.Conv2d(384, 384, 3, 1, 1),nn.ReLU(),nn.Conv2d(384, 256, 3, 1, 1),nn.ReLU(),nn.MaxPool2d(3, 2))# 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合self.fc = nn.Sequential(nn.Linear(256*5*5, 4096),nn.ReLU(),nn.Dropout(0.5),#由于使用CPU镜像,精简网络,若为GPU镜像可添加该层#nn.Linear(4096, 4096),#nn.ReLU(),#nn.Dropout(0.5),# 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000nn.Linear(4096, 10),)def forward(self, img):feature = self.conv(img)output = self.fc(feature.view(img.shape[0], -1))return output# 新建AlexNet网络net = AlexNet()
2.3 加载数据集
# 加载Fashion MNIST数据集def load_data_fashion_mnist(batch_size, resize=None, root='/home/kesci/input/FashionMNIST2065'):"""Download the fashion mnist dataset and then load into memory."""trans = []if resize:trans.append(torchvision.transforms.Resize(size=resize))trans.append(torchvision.transforms.ToTensor())transform = pose(trans)mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, download=True, transform=transform)mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, download=True, transform=transform)train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=2)test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=2)return train_iter, test_iterbatch_size = 16# 如出现“out of memory”的报错信息,可减小batch_size或resizetrain_iter, test_iter = load_data_fashion_mnist(batch_size,224)
2.4 训练网络
lr, num_epochs = 0.001, 3optimizer = torch.optim.Adam(net.parameters(), lr=lr)# .train_ch5()函数在LeNet模型中已经定义,不在重复定义d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)