卷积神经网络的基本结构#
学习目标与记号#
准确解释卷积层、激活层与池化层;
根据公式和张量维度分析展平,并识别常见实现错误;
用
Python实现或验证分类输出层;在其他条件相同的情况下,只改变一个需要研究的因素进行比较,并根据实验结果分析该因素可能带来的影响。
本节沿用统一记号:普通小写字母表示标量,粗体小写字母表示向量,粗体大写字母表示矩阵或高阶张量,层编号写作上标 \([l]\)。用 \(m\) 表示一个批量中的图片数,用 \(d_C^{[l]}\)、\(d_H^{[l]}\) 和 \(d_W^{[l]}\) 分别表示第 \(l\) 层输出的通道数、高和宽。第 \(l\) 层的卷积核尺寸、填充、步幅和空洞率分别写作 \(f_1^{[l]}\times f_2^{[l]}\)、\(p_1^{[l]}\times p_2^{[l]}\)、\(s_1^{[l]}\times s_2^{[l]}\) 和 \(r_1^{[l]}\times r_2^{[l]}\);若两个方向设置相同,则分别简写为 \(f^{[l]}\)、\(p^{[l]}\)、\(s^{[l]}\) 和 \(r^{[l]}\)。除非另有说明,本节令 \(r_1^{[l]}=r_2^{[l]}=1\)。程序采用 NCHW 排列,即批量轴位于最前。正文与练习中的程序都应同时检查数值结果和数组维度。本节练习的参考答案见 CNN 基本模块与维度传播答案。
本节把 二维卷积 与 多通道卷积 组织为网络层;梯度计算见 卷积与池化的后向传播。
CNN 通常把卷积、归一化、激活和下采样组织成若干模块,再接任务相关的输出头。理解每一层时,应同时跟踪四件事:张量维度、感受野、参数量和是否引入非线性。
基本框架
经典卷积神经网络通常由卷积层、池化层和全连接层组成。卷积层提取局部特征,池化层在每个通道内汇总局部信息并降低空间分辨率,全连接层或其他任务输出部分则根据已经提取的特征完成分类、检测或分割等任务。现代网络不一定同时使用这三类层,例如可以用带步幅的卷积代替池化,也可以用全局平均池化减小全连接部分的规模。
随着网络加深,通道数 \(d_C^{[l]}\) 通常逐步增加,而特征图的高 \(d_H^{[l]}\) 和宽 \(d_W^{[l]}\) 通常逐步减小。这样的设计使网络在减少空间位置数量的同时,可以用更多通道记录不同类型的特征,但它不是所有网络都必须遵循的硬性规则。
若要把第 \(L-2\) 层的特征图接入全连接层,可以对每个样本执行展平(flatten)。记第 \(i\) 个样本展平后的列向量为 \(\ba_i^{[L-1]}\),则得到下面这个二维矩阵:
展平只改变元素的排列方式,不引入新的模型参数。展平后的元素个数必须由前一层的实际输出维度计算,不能凭经验写成一个固定数值。
卷积层#
先考虑单输入通道、单输出通道以及步幅 1、无填充、空洞率 1 的情形。把线性输出和激活输出分开记为
矩阵形式简记为
其中 \(\ast\) 表示本章采用的互相关运算,偏置 \(b^{[l]}\) 在同一输出通道的所有空间位置共享。
对于包含 \(m\) 张图片的批量,第 \(l\) 个卷积层涉及的张量维度为
其中,\(\bW^{[l]}\) 中的维度的第一个分量 \(d_C^{[l]}\) 表示输出通道数,第二个分量 \(d_C^{[l-1]}\) 表示输入通道数。每个输出通道有一个偏置,它在该通道的所有空间位置和批量中的所有图片上共享。程序可以把偏置保存为长度为 \(d_C^{[l]}\) 的向量,参与计算时再将其理解为 \(d_C^{[l]}\times1\times1\) 并进行广播。
第 \(l\) 层的批量前向传播可以简写为
若每个输出通道都使用一个偏置,则该层参数量为
该参数量与输入的空间尺寸 \(d_H^{[l-1]}\times d_W^{[l-1]}\) 无关。若卷积后紧接 Batch Normalization,实践中常关闭卷积偏置,此时应去掉上式中的 1。
卷积层的结构体现了我们对图像数据的两个基本认识:
局部连接:每个输出位置只读取输入的一个局部窗口。堆叠多层后,深层单元的有效感受野逐步扩大。
参数共享:同一个核在所有空间位置复用。这使卷积对平移近似等变,并显著减少参数量。
参数共享不等于严格的平移不变性。边界填充、步幅和下采样都会影响等变性质;分类输出的近似不变性通常由全局池化和数据增强进一步获得。
输出尺寸#
对第 \(l\) 个卷积层,输入特征图的高和宽为 \(d_H^{[l-1]}\)、\(d_W^{[l-1]}\),卷积核尺寸为 \(f_1^{[l]}\times f_2^{[l]}\),填充为 \(p_1^{[l]}\times p_2^{[l]}\),步幅为 \(s_1^{[l]}\times s_2^{[l]}\),空洞率为 \(r_1^{[l]}\times r_2^{[l]}\)。输出空间尺寸为
输出张量的完整维度为 \(m\times d_C^{[l]}\times d_H^{[l]}\times d_W^{[l]}\)。实现网络时应逐层核对这个维度,特别是在卷积模块与全连接层相接的位置。
下采样
增大卷积步幅、采用池化或其他重采样操作都可以减小空间分辨率。下采样减少计算量并扩大后续单元相对于原图的感受野,但也会丢失细粒度位置信息;检测和分割任务常通过多尺度特征或上采样路径补回细节。
池化层#
池化在每个通道上独立汇总局部窗口,不含可训练权重。记第 \(l\) 个卷积层的激活输出为 \(\bA^{[l]}\),紧随其后的池化层输出为 \(\bP^{[l+1]}\)。设池化窗口大小为 \(f_1^{[l+1]}\times f_2^{[l+1]}\)、步幅为 \(s_1^{[l+1]}\times s_2^{[l+1]}\)。不考虑填充时,第 \(c\) 个通道的最大池化与平均池化分别为
其中,池化不会把不同通道混在一起,因此 \(d_C^{[l+1]}=d_C^{[l]}\);它只根据窗口、填充和步幅改变高和宽。若池化不使用空洞窗口,其输出高和宽可以用式 (86) 计算,只需令两个方向的空洞率都为 1。
最大池化保留窗口中的强响应,平均池化保留平均水平。池化本身没有参数,但会改变后续层的计算量和信息保留方式,也可能降低模型对轻微局部变化的敏感程度,因此不能简单地说它必然防止过拟合。现代分类网络也常使用带步幅卷积完成下采样,并在末端使用全局平均池化,把每个通道的整个特征图压缩为一个数。
从特征提取到任务输出#
图 15 卷积神经网络的基本结构#
特征提取主干:重复使用卷积块,通常在通道数增加的同时逐步降低空间分辨率。浅层卷积核通常更容易响应边缘、颜色变化和简单纹理;中间层可以组合这些局部响应,形成纹理片段、角点或物体局部结构;更深层的特征具有更大的感受野,因而能够组合出与任务相关的较复杂模式。这只是常见现象,不能把每一层机械地解释为固定语义。Zeiler 和 Fergus(2014) 通过特征可视化展示了这种由简单到复杂的层级变化。
任务输出头:分类可采用全局平均池化加线性层;检测和分割会保留多尺度空间特征,并使用专门的预测头。全连接层不是所有 CNN 的必需组成,也不应笼统地称为模型的“记忆模块”。
图片翻转、裁剪、缩放、颜色扰动和加入适量噪声等数据增强方法,可以从已有训练图片构造合理的变化版本,帮助模型减少对偶然位置、方向或颜色的依赖。数据增强只能用于训练集,并且变换后不应改变观测标签的含义。具体程序将在 用 ResNet-18 分类 CIFAR-10 中介绍。
卷积与池化的后向传播 将从局部窗口的依赖关系出发,说明梯度怎样传播回输入和参数。
Shiny 交互演示:池化计算
下面的交互页面可以比较最大池化和平均池化,并观察池化窗口、步长与填充怎样影响输出。页面会保留二维输出,给出输出维度和参数有效性提示,并说明最大池化与平均池化对填充值的不同处理方式。
核心推导与实现核验#
核心关系
推导路径。 卷积产生线性响应,偏置按输出通道广播,激活逐元素作用;池化只改变预定空间窗口,展平后才接全连接分类输出层。
关键条件
最大池化在每个窗口选择最大值,因此对窗口内元素的任意排列保持输出不变,但窗口移动或边界变化仍可改变结果。
数据规模
卷积和池化都不会改变一个批量中的图片数 \(m\)。卷积层可以改变通道数以及图像的高和宽,池化层通常保持通道数不变并缩小高和宽;送入全连接层前,每个样本需要展平为 \(d_C^{[l]}d_H^{[l]}d_W^{[l]}\) 个数,这个数必须根据前一层的实际输出计算。
常见误区
如果在代码中直接填写卷积输出展平后的长度,那么输入图像大小、卷积核、填充或步幅发生变化后,全连接层的输入维度就可能不再匹配。池化通常只在特征图的高度和宽度方向进行,并分别处理每个通道;如果错误地在通道方向上池化,就会混合或丢失不同通道记录的特征。
动手检查
用全 1 输入、单位脉冲输入和非对称核核对索引、核方向与输出尺寸,再与框架 conv2d 在相同约定下比较。
本节小结#
CNN 模块的连接必须保持批量、通道和空间轴语义。
池化无参数但会改变信息与梯度路径。
分类输出层输入维度应从实际特征图推导。
综合练习#
程序题应固定随机种子、写出维度断言并报告运行环境;比较题还应固定数据划分、随机种子集合和训练预算。全部参考答案见 CNN 基本模块与维度传播答案。
维度与参数量计算。 输入维度为 \(m\times3\times32\times32\),依次经过“8 个 \(3\times3\)、步幅 1、填充 1 的卷积核”“\(2\times2\)、步幅 2 的池化”“16 个 \(3\times3\)、步幅 1、填充 1 的卷积核”“全局平均池化”和 10 类线性层。写出每层输出维度并计算含偏置的总参数量。
感受野计算。 从感受野 \(r_0=1\)、相邻特征点在输入上的间隔 \(j_0=1\) 出发,使用 \(r_l=r_{l-1}+(f^{[l]}-1)j_{l-1}\)、\(j_l=j_{l-1}s^{[l]}\),计算“\(3\times3\) 卷积、\(2\times2\) 步幅 2 池化、\(3\times3\) 卷积”之后的感受野和间隔。
池化具体计算。 对 \(4\times4\) 特征图 \(\begin{bmatrix}1&2&3&4\\5&6&7&8\\9&10&11&12\\13&14&15&16\end{bmatrix}\),分别计算核大小 \(2\times2\)、步幅 2 的最大池化和平均池化输出。
池化性质。 证明最大池化对同一个池化窗口内部元素的任意排列保持不变;再构造一个最小例子说明,当输入平移导致窗口划分改变时,整个池化输出不一定保持不变。
模型与维度跟踪实现。 用
Python实现第 1 题的小型 CNN,并编写维度跟踪器记录每一层的输入/输出维度、参数量和中间激活元素数;分类输出层输入维度应由虚拟前向传播确定,而不是手工写死。框架对照。 用卷积与池化输出尺寸公式手工计算第 5 题所有维度,再与框架前向钩子的记录逐层比较;手工统计参数量并与
sum(p.numel() for p in model.parameters())核对。测试设计。 测试不同批量大小不改变除批次轴外的维度、最小合法空间尺寸能够前向、错误通道数会失败、全局平均池化输出与手工均值一致,以及一个前向—损失—后向步骤产生与所有可训练参数同形的有限梯度。
CNN 与 MLP 比较。 在同一图像分类数据上比较小型 CNN 与参数量尽量接近的 MLP。固定训练/验证/测试划分、随机种子集合、训练预算和超参数选择预算;报告任务性能、训练时间、固定批量预测时间、参数量及峰值内存。
下采样方法比较。 在同一 CNN 中比较最大池化、平均池化和步幅卷积,并尽量匹配输出维度与模型容量。固定数据划分、随机种子集合和训练预算;报告任务性能、训练时间、固定批量预测时间、参数量、乘加量及峰值内存。
网络宽度比较。 把两个卷积层的通道数同时乘以 \(0.5,1,2\),其他结构不变。固定数据划分、随机种子集合、优化器和训练预算;报告任务性能、训练时间、固定批量预测时间、参数量及峰值内存,并讨论容量收益与计算代价。