一、AlexNet网络
AlexNet是2012年ImageNet竞赛冠军获得者Hinton和他的学生Alex Krizhevsky设计的。AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中,其中引入了很多创新点(将在铺垫知识详细介绍)因此具有更强的图像处理效果。
二、铺垫知识
(一)ReLU
采用ReLU的深度卷积神经网络训练时间比等价的tanh
单元要快几倍。于一个特定的四层卷积网络,在CIFAR-10数据集上达到25%的训练误差所需要的迭代次数可以证实这一点。下面是ReLU函数相比于Sigmoid和tanh的优点:(参考:https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/119604015)
1.相比起Sigmoid和tanh,ReLU在SGD中能够快速收敛,这是因为它线性(linear)、非饱和(non-saturating)的形式。
2.Sigmoid和tanh涉及了很多很expensive的操作(比如指数),ReLU可以更加简单的实现。
3.有效缓解了梯度消失的问题。
4.在没有无监督预训练的时候也能有较好的表现。
(二)Dropout
深度学习可能存在过拟合问题,而Dropout正则化可以随机删除网络中的神经单元,不贡献连接权重而减少过拟合风险。同时强迫这些神经元去学习互补的一些特征。
(它会以0.5的概率对每个隐层神经元的输出设为0。那些“失活的”的神经元不再进行前向传播并且不参与反向传播。因此每次输入时,神经网络会采样一个不同的架构,但所有架构共享权重。这个技术减少了复杂的神经元互适应,因为一个神经元不能依赖特定的其它神经元的存在。因此,神经元被强迫学习更鲁棒的特征,它在与许多不同的其它神经元的随机子集结合时是有用的。)
(三)GPU
由于无网络太大,不能在单个GPU上进行训练,因此作者将网络分布在两个GPU
上。并且规定只在某些特定的层上进行GPU
通信,每个GPU
放置一半的核(或神经元),不但提高了计算速度而且降低了错误率。
(四)Overlapping Pooling
重叠池化:习惯上,相邻池化单元归纳的区域是不重叠的,而重叠池化的池化步伐小于池化核,从而池化结果实现重叠。目的:实验发现在训练过程中通常观察采用重叠池化的模型,发现它更难过拟合。
(五)LRN
LRN (局部响应归一化)是一种提高深度学习准确度的技术方法。LRN 一般是在激活、池化函数后的一种方法。
在 ALexNet 中,提出了 LRN 层,对局部神经元的活动创建竞争机制,使其中响应比较大对值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
局部响应归一化,在ReLU激活后面加上LRN,从而有助于泛化。(BN是批归一化)下面是LRN公式:
三、网络框架
下图是alexnet网络框架图,网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax
的输入,softmax
会产生1000类标签的分布。
如图所示分为两层,两层在两块GPU上运行;
第2,4,5卷积层的核只与位于同一GPU上的前一层的核映射相连接;
第3卷积层的核与第2层的所有核映射相连;
全连接层的神经元与前一层的所有神经元相连;
在第1,2卷积层之后是局部响应归一化层LRN;
在响应归一化层LPN和第5卷积层之后是重叠池化;
在每个卷积层和全连接层的输出上是ReLU函数;
在第1,2,5层后面是重叠池化;
在前两个全连接层是Dropout。
(一)C1
输入图片:227 × 227 × 3
卷积:11×11×3,步长为4,卷积核为96
特征图像:55×55×96【(227-11)/4+1=55】
ReLU:激活函数
池化: 27×27×96【(55-3)/2+1=27】 kernel size3,stride2
LRN:局部响应归一化处理
(二)C2
输入图片:27×27×96为方便计算经过2像素扩展为31×31×96后分为两组为31×31×48
每组卷积:5×5×48,步长为1,卷积核为128
特征图像:27×27×128【(31-5)/1+1=27】
ReLU:激活函数
池化: 13×13×128【(27-3)/2+1=13】 kernel size3,stride2
LRN:局部响应归一化处理
(三)C3
输入图片:每组13×13×128为方便计算经过1像素扩展为15×15×128
每组卷积:3×3×128,步长为1,卷积核为192
特征图像:13×13×192【(15-3)/1+1=13】
ReLU:激活函数
(四)C4
输入图片:每组13×13×192为方便计算经过1像素扩展为15×15×192
每组卷积:3×3×192,步长为1,卷积核为192
特征图像:13×13×192【(15-3)/1+1=13】
ReLU:激活函数
(五)C5
输入图片:每组13×13×192为方便计算经过1像素扩展为15×15×192
每组卷积:3×3×192,步长为1,卷积核为128
特征图像:13×13×128【(15-3)/1+1=13】
ReLU:激活函数
每组池化:6×6×128【(13-3)/2+1=6】 kernel size3,stride2
LRN:局部响应归一化处理
(六)F1
输入图片:6×6×256
滤波器:6×6×256,4096个
神经元:4096个神经元
输出:4096×1
ReLU
dropout
(七)F2
输入:4096×1
神经元:4096个神经元
输出:4096×1
ReLU
dropout
(八)F3
输入:4096×1
神经元:1000个神经元
输出:1000×1
ReLU
dropout
四、代码实现Pytorch
import torch.nn as nn
import torch
class AlexNet(nn.Module):
def __init__(self, num_classes=1000, init_weights=False):
super(AlexNet, self).__init__()
self.features = nn.Sequential( #打包
nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # input[3, 224, 224] output[48, 55, 55] 自动舍去小数点后
nn.ReLU(inplace=True), #inplace 可以载入更大模型
nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27, 27] kernel_num为原论文一半
nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13]
nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13]
nn.ReLU(inplace=True),
nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128, 13, 13]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6]
)
self.classifier = nn.Sequential(
nn.Dropout(p=0.5),
#全链接
nn.Linear(128 * 6 * 6, 2048),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(2048, 2048),
nn.ReLU(inplace=True),
nn.Linear(2048, num_classes),
)
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, start_dim=1) #展平 或者view()
x = self.classifier(x)
return x
参考:
论文连接https://proceedings.neurips.cc/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf