系列文章目录
第二章 深度学习 CNN中的深度卷积神经网络(AlexNet)
目录
系列文章目录
文章目录
前言
一、深度卷积神经网络(AlexNet)是什么?
二、AlexNet的网络结构
三、实现AlexNet模型
总结
前言
本文主要是介绍卷积神经网络中的深度卷积神经网络(AlexNet),它包含对深度卷积神经网络(AlexNet)一个简单的介绍,以及如何实现LeNet?读完这篇文章,你会对卷积神经网络(LeNet)有个基本的了解。
一、深度卷积神经网络(AlexNet)是什么?
深度卷积神经网络(AlexNet)是在2012年提出来的。这个模型的名字来源于论文第一作者的姓名Alex Krizhevsky 。AlexNet使用了8层卷积神经网络,并以很大的优势赢得了ImageNet 2012图像识别挑战赛。
AlexNet与LeNet的设计理念非常相似,但也有显著的区别,下面我们会提到。
Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). Imagenet classification with deep convolutional neural networks. In Advances in neural information processing systems (pp. 1097-1105).
二、AlexNet的网络结构
我们来了解下AlexNet的网络结构,如下图所示:
可以看出AlexNet与LeNet的网络结构非常相似,这里我们重点阐述两者的区别,从而了解AlexNet的网络结构。(如果需要了解LeNet网络可以参考:(3条消息) 【CNN】卷积神经网络(LeNet)是什么?如何实现LeNet?_晓亮.的博客-CSDN博客https://blog.csdn.net/m0_51816252/article/details/130657443
第一,与相对较小的LeNet相比,AlexNet包含8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。
AlexNet第一层中的卷积窗口形状是11×11。因为ImageNet中绝大多数图像的高和宽均比MNIST图像的高和宽大10倍以上,ImageNet图像的物体占用更多的像素,所以需要更大的卷积窗口来捕获物体。
第二层中的卷积窗口形状减小到5×5,之后全采用3×3。此外,第一、第二和第五个卷积层之后都使用了窗口形状为3×3、步幅为2的最大池化层。而且,AlexNet使用的卷积通道数也大于LeNet中的卷积通道数数十倍。最后一个卷积层的是两个输出个数为4096的全连接层。
第二,AlexNet将sigmoid激活函数改成了更加简单的ReLU激活函数。
一方面,ReLU激活函数的计算更简单,例如它并没有sigmoid激活函数中的求幂运算。另一方面,ReLU激活函数在不同的参数初始化方法下使模型更容易训练。这是由于当sigmoid激活函数输出极接近0或1时,这些区域的梯度几乎为0,从而造成反向传播无法继续更新部分模型参数;而ReLU激活函数在正区间的梯度恒为1。因此,若模型参数初始化不当,sigmoid函数可能在正区间得到几乎为0的梯度,从而令模型无法得到有效训练。
第三,AlexNet通过丢弃法(dropout)来控制全连接层的模型复杂度。而LeNet并没有使用丢弃法。
第四,AlexNet引入了大量的图像增广,如翻转、裁剪和颜色变化,从而进一步扩大数据集来缓解过拟合。
三、实现AlexNet模型
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride, padding
nn.ReLU(),
nn.MaxPool2d(3, 2), # kernel_size, stride
# 减小卷积窗口,使用填充为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),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
# 输出层。
nn.Linear(4096, 1000),
)
def forward(self, img):
feature = self.conv(img)
output = self.fc(feature.view(img.shape[0], -1))
return output
创建完模型后,我们可以输入下面代码来查看每个层的形状。
net = AlexNet()
print(net)
这里我直接给出输出结果:
AlexNet(
(conv): Sequential(
(0): Conv2d(1, 96, kernel_size=(11, 11), stride=(4, 4))
(1): ReLU()
(2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(3): Conv2d(96, 256, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(4): ReLU()
(5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Conv2d(256, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(7): ReLU()
(8): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(9): ReLU()
(10): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU()
(12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(fc): Sequential(
(0): Linear(in_features=6400, out_features=4096, bias=True)
(1): ReLU()
(2): Dropout(p=0.5)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU()
(5): Dropout(p=0.5)
(6): Linear(in_features=4096, out_features=1000, bias=True)
)
)
我们可以看见模型包含8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。
总结
读完这篇文章,我相信你已经对深度卷积神经网络(AlexNet)有了一个基本的了解了,AlexNet的出现,它首次证明了学习到的特征可以超越手工设计的特征,这在当时是一个很大的突破。希望大家读完这篇文章能够有所收获。