本章将介绍现代的 卷积神经网络架构,许多现代卷积神经网络的研究都是建立在这一章的基础上的。在本章中的每一个模型都曾一度占据主导地位,其中许多模型都是 ImageNet竞赛 的优胜者。ImageNet竞赛自2010年以来,一直是计算机视觉中监督学习进展的指向标。
- AlexNet。它是第一个在大规模视觉竞赛中击败 传统计算机视觉模型 的大型神经网络;
- 使用重复块的网络(VGG)。它 利用许多重复的神经网络块;
- 网络中的网络(NiN)。它 重复使用由卷积层和1 × 1卷积层(用来代替全连接层)来构建深层网络;
- 含并行连结的网络(GoogLeNet)。它使用 并行连结的网络,通过不同窗口大小的卷积层和最大汇聚层 来并行抽取信息;
- 残差网络(ResNet)。它 通过残差块构建跨层的数据通道,是计算机视觉中最流行的体系架构;
- 稠密连接网络(DenseNet)。它的计算成本很高,但给我们带来了更好的效果。
虽然深度神经网络的概念非常简单——将神经网络堆叠在一起。但由于不同的网络架构和超参数选择,这些 神经网络的性能会发生很大变化。
一 深度卷积神经网络(AlexNet)
卷积神经网络的输 入是 由原始像素值或是经过简单预处理的像素值组成的。但在使用传统机器学习方法时, 从业者永远不会将原始像素作为输入。在 传统机器学习 方法中,计算机视觉流水线是 由经过人的手工精心设 计的特征流水线组成的。对于这些传统方法,大部分的进展都来自于对特征有了更聪明的想法,并且学习到的算法往往归于事后的解释。
因此,与训练端到端(从像素到分类结果)系统不同,经典机器学习的流水线 看起来更像下面这样:
- 获取一个有趣的数据集。在早期,收集这些数据集需要昂贵的传感器(在当时最先进的图像也就100万 像素)。
- 根据光学、几何学、其他知识以及偶然的发现,手工对特征数据集进行预处理。
- 通过 标准的特征提取算法,如SIFT(尺度不变特征变换)(Lowe, 2004)和SURF(加速鲁棒特征)(Bay et al., 2006)或其他手动调整的流水线来输入数据。
- 将 提取的特征送入最喜欢的分类器 中(例如线性模型或其它核方法),以训练分类器。
计算机视觉研究人员会告诉一个诡异事实——推动领域进步的是数据特征,而不是学习算法。计算机视觉研究人员相信,从对最终模型精度的影响来说,更大或更干净的数据集、或是稍微改进的特征提取,比任何学习算法带来的进步要大得多。
1.1 学习表征
另一种预测这个领域发展的方法——观察图像特征的提取方法。在2012年前,图像特征都是机械地计算出 来的。事实上,设计一套新的特征函数、改进结果,并撰写论文是盛极一时的潮流。SIFT (Lowe, 2004)、SURF (Bay et al., 2006)、HOG(定向梯度直方图)(Dalal and Triggs, 2005)、bags of visual words88和类似的特征提 取方法占据了主导地位。
另一组研究人员,包括Yann LeCun、Geoff Hinton、Yoshua Bengio、Andrew Ng、Shun ichi Amari和Juergen Schmidhuber,想法则与众不同:他们认为特征本身应该被学习。此外,他们还认为,在合理地复杂性前提下, 特征应该由多个共同学习的神经网络层组成,每个层都有可学习的参数。在机器视觉中,最底层可能 检测边缘、颜色和纹理。事实上,Alex Krizhevsky、Ilya Sutskever和Geoff Hinton提出了一种新的卷积神经网络变体AlexNet。在2012年ImageNet挑战赛中取得了轰动一时的成绩。
有趣的是,在网络的最底层,模型学习到了一些 类似于传统滤波器的特征抽取器。
1.2 AlexNet 网络结构
AlexNet 和 LeNet 的设计理念非常相似,但也存在显著差异。
- AlexNet比相对较小的LeNet5要深得多。AlexNet由八层组成:五个卷积层、两个全连接隐藏层和一个 全连接输出层。
- AlexNet使用 ReLU 而不是sigmoid作为其激活函数。
在AlexNet的第一层,卷积窗口的形状是11×11。由于ImageNet中大多数图像的宽和高比MNIST图像的多10倍 以上,因此,需要一个更大的卷积窗口来捕获目标。第二层中的卷积窗口形状被缩减为5×5,然后是3×3。此 外,在第一层、第二层和第五层卷积层之后,加入窗口形状为3 × 3、步幅为2的最大汇聚层。而且,AlexNet的 卷积通道数目是LeNet的10倍。
ReLU激活函 数使训练模型更加容易。当sigmoid激活函数的输出非常接近于0或1时,这些区域的梯度几乎为0,因此反向 传播无法继续更新一些模型参数。相反,ReLU激活函数在正区间的梯度总是1。
AlexNet通过暂退法控制全连接层的模型复杂度,而LeNet只使用了权重衰减。为了进一步扩充数 据,AlexNet在训练时 增加了大量的图像增强数据,如翻转、裁切和变色。这使得模型更健壮,更大的样本量 有效地减少了过拟合。
import torch
from torch import nn
from d2l import torch as d2l
net = 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.Linear(6400, 4096), nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096), nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, 10)
)
我们构造一个高度和宽度都为224的单通道数据,来观察每一层输出的形状。
X = torch.randn(1, 1, 224, 224)
for layer in net:
X=layer(X)
print(layer.__class__.__name__,'output shape:\t',X.shape)
# Conv2d output shape: torch.Size([1, 96, 54, 54])
# ReLU output shape: torch.Size([1, 96, 54, 54])
# MaxPool2d output shape: torch.Size([1, 96, 26, 26])
# Conv2d output shape: torch.Size([1, 256, 26, 26])
# ReLU output shape: torch.Size([1, 256, 26, 26])
# MaxPool2d output shape: torch.Size([1, 256, 12, 12])
# Conv2d output shape: torch.Size([1, 384, 12, 12])
# ReLU output shape: torch.Size([1, 384, 12, 12])
# Conv2d output shape: torch.Size([1, 384, 12, 12])
# ReLU output shape: torch.Size([1, 384, 12, 12])
# Conv2d output shape: torch.Size([1, 256, 12, 12])
# ReLU output shape: torch.Size([1, 256, 12, 12])
# MaxPool2d output shape: torch.Size([1, 256, 5, 5])
# Flatten output shape: torch.Size([1, 6400])
# Linear output shape: torch.Size([1, 4096])
# ReLU output shape: torch.Size([1, 4096])
# Dropout output shape: torch.Size([1, 4096])
# Linear output shape: torch.Size([1, 4096])
# ReLU output shape: torch.Size([1, 4096])
# Dropout output shape: torch.Size([1, 4096])
# Linear output shape: torch.Size([1, 10])
1.3 使用AlexNet 训练
尽管原文中AlexNet是在ImageNet上进行训练的,但本书在这里使用的是Fashion‐MNIST数据集。
# 读取数据
batch_size = 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
这里的主要变化是使用更小的学习速率训练,这 是因为网络更深更广、图像分辨率更高,训练卷积神经网络就更昂贵。
lr, num_epochs = 0.01, 10
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
小结:
- AlexNet的架构与LeNet相似,但 使用了更多的卷积层和更多的参数 来拟合大规模的ImageNet数据集。
- 今天,AlexNet已经被更有效的架构所超越,但它是从浅层网络到深层网络的关键一步。
- 尽管AlexNet的代码只比LeNet多出几行,但学术界花了很多年才接受深度学习这一概念,并应用其出 色的实验结果。这也是由于缺乏有效的计算工具。
- Dropout、ReLU和预处理 是提升计算机视觉任务性能的其他关键步骤。