本文是日常学习总结,内容均为原创,未经博主允许不得转载。
论文:AlexNet原文(可能加载较慢,稍等即可)
AlexNet由Alex Krizhevsky于2012年提出,夺得2012年ILSVRC比赛的冠军,top5预测的错误率为16.4%,它以领先第二名10%的准确率夺得冠军,并且成功的向世界展示了深度学习的魅力。
此部分很重要,我上篇文章讲的LeNet,身为深度学习的小白,喜欢边学习边总结。为什么AlexNet会比LeNet好?他有哪些创新点?这些点是否对我们自己的网络有作用,比如LRN。我们是否可以受到启发,从而改进自己网络!
AlexNet为一个8层深度网络,其中5层卷积层和3层全连接层(不包括LRN和池化层)。如下图所示:
上图可能看的比较混乱,那时因为当时GPU计算能力不强,而AlexNet又比较复杂,所以Alex使用了两个GPU并行来做运算。现在完全以及可以用一个GPU代替了,所以我们接下来皆以一个GPU介绍。
网络最初的输入是224*224*3(RGB图像),但实际上会经过预处理变为227*227*3,即对于Conv1来说,输入为227*227*3。
这个图像被11*11*3(3代表深度,例如RGB的3通道)的卷积核进行卷积运算,依据公式:【input_size - kernel_size + 2*padding】/ stride + 1 = output_size (其中【】表示向下取整),所以我们的得到的第一个特征图大小为:[227 - 11 + 2*0] / 4 + 1 = 55 , 由于一共有96个卷积核,故特征图规格为:55*55*96。Ps:在图一中我们看到48的深度是因为当时用的双GPU,数据被分为两组了,即48*2 = 96。
重叠pool池化层:这些像素层还需要经过pool运算(池化运算)的处理,池化运算的尺度由预先设定为3*3,运算的步长为2,则池化后的图像的尺寸为:(55-3)/2+1=27。即经过池化处理过的规模为27*27*96。
具体运算过程与第一层大致相同,运算结果见图,故不重复叙述。(下同)
这里使用4096个神经元,对256个大小为6*6特征图,进行一个全链接,也就是将6*6大小的特征图,进行卷积变为一个特征点,然后对于4096个神经元中的一个点,是由256个特征图中某些个特征图卷积之后得到的特征点乘以相应的权重之后,再加上一个偏置得到。
再进行一个dropout随机从4096个节点中丢掉一些节点信息(也就是值清0),然后就得到新的4096个神经元。(dropout可以有效的减轻过拟合现象)。(下同)
import torch
import torch.nn as nn
class AlexNet(nn.Module): #定义网络,推荐使用Sequential,结构清晰
def __init__(self):
super(AlexNet,self).__init__()
self.conv1 = torch.nn.Sequential( #input_size = 227*227*3
torch.nn.Conv2d(in_channels=3,out_channels=96,kernel_size=11,stride=4,padding=0),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=3, stride=2) #output_size = 27*27*96
)
self.conv2 = torch.nn.Sequential( #input_size = 27*27*96
torch.nn.Conv2d(96, 256, 5, 1, 2),
torch.nn.ReLU(),
torch.nn.MaxPool2d(3, 2) #output_size = 13*13*256
)
self.conv3 = torch.nn.Sequential( #input_size = 13*13*256
torch.nn.Conv2d(256, 384, 3, 1, 1),
torch.nn.ReLU(), #output_size = 13*13*384
)
self.conv4 = torch.nn.Sequential( #input_size = 13*13*384
torch.nn.Conv2d(384, 384, 3, 1, 1),
torch.nn.ReLU(), #output_size = 13*13*384
)
self.conv5 = torch.nn.Sequential( #input_size = 13*13*384
torch.nn.Conv2d(384, 256, 3, 1, 1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(3, 2) #output_size = 6*6*256
)
#网络前向传播过程
self.dense = torch.nn.Sequential(
torch.nn.Linear(9216, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(4096, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(4096, 50)
)
def forward(self, x): #正向传播过程
conv1_out = self.conv1(x)
conv2_out = self.conv2(conv1_out)
conv3_out = self.conv3(conv2_out)
conv4_out = self.conv4(conv3_out)
conv5_out = self.conv5(conv4_out)
res = conv5_out.view(conv5_out.size(0), -1)
out = self.dense(res)
return out