深度学习经典模型:AlexNet的结构与代码实现
深度学习经典模型:AlexNet的结构与代码实现
AlexNet是深度学习领域的一个里程碑式模型,由Hinton和他的学生Alex Krizhevsky在2012年提出,首次在ImageNet大规模视觉识别挑战赛中取得突破性成果。本文将详细介绍AlexNet的网络结构、关键创新点,并通过代码实现帮助读者理解这一经典模型。
什么是AlexNet
AlexNet是2012年提出的一个深度卷积神经网络(CNN),由ImageNet大规模视觉识别挑战赛冠军获得者Hinton和他的学生Alex Krizhevsky提出,标志着深度学习在计算机视觉领域的突破。下图为AlexNet架构图:
AlexNet和上一节讲解的LeNet网络的设计理念和架构非常相似,但也存在很大的差异。
首先,AlexNet输入层尺寸变为224x224x3,意味着识别RGB通道为3的彩色图像,因此AlexNet采用的是ImageNet数据集,其图像分辨率较高,需要更深层次的网络和更大的卷积核、池化核。
接下来,简单介绍AlexNet网络每一层的输入、输出以及激活函数:
第一卷积层(Conv1)的卷积核大小为11x11×3,步长为4,卷积核数量为96,输出尺寸为55x55x96(因为实验中使用两个GPU进行计算所以这里写的是一对总共的数量),激活函数使用ReLU。
第一池化层(Pool1)采用最大池化(Max Pooling),池化窗口大小为3x3,步长为2,输出尺寸为27x27x96,池化层用于降采样,减少计算量,同时增强特征的平移不变性。池化后进行LRN(局部响应归一化)处理,提高模型的泛化能力。
第二卷积层(Conv2)的卷积核大小为5x5,数量256,步长为1,填充为2,输出尺寸为27x27x256,因使用填充(padding)所以特征图尺寸不变,同时增加通道数以提取更多特征。也使用ReLU激活函数。
第二池化层(Pool2)采用最大池化且池化窗口大小为3x3,步长为2,输出尺寸为13x13x256,进一步降采样,减少计算量。
第三、四、五层卷积层(Conv3、Conv4、Conv5):均采用 3x3 的卷积核,步长填充均为 1,三四层卷积核数为384,第五层为256,均使用ReLU激活函数。
第三池化层(Pool3)池化窗口大小为3x3,步长2,输出尺寸6x6x256,最终降采样,为全连接层准备数据。
第一、二全连接层(FC1、FC2)神经元数量均为4096,激活函数为ReLU,Dropout:在训练时使用Dropout,丢弃概率为0.5。全连接层将卷积层提取的特征进行组合,用于分类。
输出层(Output Layer)神经元数量为1000(对应ImageNet的1000个类别)激活函数Softmax,输出1000个类别的概率分布。
我们发现,AlexNet在激活函数的使用上有很大进步,与LeNet使用的Sigmoid不同,ReLU能够加速训练并缓解梯度消失问题,成功解决了Sigmoid在网络较深时的梯度弥散问题。
除此之外,AlexNet训练时使用Dropout随机忽略一部分神经元,以避免模型过拟合。Dropout率为0.5代表着每个神经元有 50%的概率不参与计算,成功防止过拟合问题。
AlexNet全部使用最大池化,避免平均池化的模糊化效果。并且AlexNet采用数据增强(如翻转、平移等)提升泛化能力,并利用GPU加速训练,大幅缩短训练时间。还提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
因此,在性能上,AlexNet取得了很大突破,能够在ImageNet等大规模数据集上表现优异,推动了深度学习的发展,开启了深度学习在计算机视觉中的广泛应用。
代码实现
首先,定义AlexNet模型,在这里使用的仍然是是Fashion-MNIST数据集,因为训练ImageNet需要几个小时甚至几天,这里仅快速演示一下AlexNet网络,所以输入的是单通道(灰度)图像,最后输出层的类别数为10。
import torch
from torch import nn
from d2l import torch as d2l
AlexNet = nn.Sequential(
nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(), # 第一层卷积
nn.MaxPool2d(kernel_size=3, stride=2), # 第一层池化
nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(), # 第二层卷积
nn.MaxPool2d(kernel_size=3, stride=2), # 第二层池化
nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(), # 第三层卷积
nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(), # 第四层卷积
nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(), # 第五层卷积
nn.MaxPool2d(kernel_size=3, stride=2), nn.Flatten(), # 第三层池化
# nn.Flatten()将多维特征图展平为一维向量,以便输入全连接层
nn.Linear(6400, 4096), nn.ReLU(), nn.Dropout(p=0.5), # 第一层全连接层,丢弃概率为0.5
nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(p=0.5), # 第二层全连接层
nn.Linear(4096, 10)) # 输出层
构造一个单通道数据,来观察每一层输出的形状。
X = torch.rand(1, 1, 224, 224) # 创建了一个随机张量
for layer in net: # 循环遍历网络net中的每一层
X = layer(X) # 将当前张量X传递给该层,并更新X为该层的输出
print(layer.__class__.__name__, 'Output shape:\t', X.shape) # 输出该层的类名以及输出张量的形状
我们可以看到每一层的形状,结合前面展示的AlexNet框架,可以检查每一层输出是否正确,也能更好的理解该模型结构。不同的是,第一层卷积使用了一个填充因此输出的是54而非前面描述的55,但原理都一样,网络架构依然是AlexNet。
读取数据集,Fashion-MNIST图像分辨率低于ImageNet图像,我们将它增加到224,调整为适合AlexNet模型训练的格式。
batch_size = 128 # 批量大小 表示每次训练会同时处理128张图像
train_iter, test_iter = d2l.load_data_fashion_mnist(
batch_size, resize=224)
# 加载Fashion-MNIST数据集 resize将图像的尺寸从默认的28x28调整为224x224
训练AlexNet:
lr, num_epochs = 0.01, 10 # 学习率、训练轮数
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
# 调用d2l.train_ch6函数训练net,训练过程中会打印训练损失、训练准确率、测试损失和测试准确率等信息
结果:
总结
总的来说,AlexNet的设计思想和成功经验对后续的神经网络发展产生了深远影响,它的设计考虑了计算效率和特征提取能力,极大地推动了深度学习的发展。