\[ \begin{align}\begin{aligned}\newcommand{\ba}{\boldsymbol{a}}
\newcommand{\bb}{\boldsymbol{b}}
\newcommand{\be}{\boldsymbol{e}}
\newcommand{\bq}{\boldsymbol{q}}
\newcommand{\bk}{\boldsymbol{k}}
\newcommand{\bw}{\boldsymbol{w}}
\newcommand{\bx}{\boldsymbol{x}}
\newcommand{\by}{\boldsymbol{y}}
\newcommand{\bz}{\boldsymbol{z}}
\newcommand{\bd}{\boldsymbol{d}}
\newcommand{\bv}{\boldsymbol{v}}
\newcommand{\bs}{\boldsymbol{s}}\\\newcommand{\btheta}{\boldsymbol{\theta}}
\newcommand{\bbeta}{\boldsymbol{\beta}}
\newcommand{\bgamma}{\boldsymbol{\gamma}}
\newcommand{\bsigma}{\boldsymbol{\sigma}}
\newcommand{\md}{\mbox{d}}
\newcommand{\bmu}{\boldsymbol{\mu}}
\newcommand{\bone}{\boldsymbol{1}}
\newcommand{\bzero}{\boldsymbol{0}}
\newcommand{\bepsilon}{\boldsymbol{\epsilon}}
\newcommand{\bphi}{\boldsymbol{\phi}}
\newcommand{\bh}{\boldsymbol{h}}
\newcommand{\bc}{\boldsymbol{c}}
\newcommand{\br}{\boldsymbol{r}}
\newcommand{\bQ}{\boldsymbol{Q}}
\newcommand{\bK}{\boldsymbol{K}}
\newcommand{\bV}{\boldsymbol{V}}
\newcommand{\bSigma}{\boldsymbol{\Sigma}}
\newcommand{\bg}{\boldsymbol{g}}
\newcommand{\bxi}{\boldsymbol{\xi}}
\newcommand{\bvarepsilon}{\boldsymbol{\varepsilon}}
\newcommand{\bdelta}{\boldsymbol{\delta}}
\newcommand{\bq}{\boldsymbol{q}}
\newcommand{\bk}{\boldsymbol{k}}
\newcommand{\bJ}{\boldsymbol{J}}
\newcommand{\bp}{\boldsymbol{p}}
\newcommand{\bi}{\boldsymbol{i}}
\newcommand{\bo}{\boldsymbol{o}}
\newcommand{\bE}{\boldsymbol{E}}
\newcommand{\bH}{\boldsymbol{H}}
\newcommand{\bL}{\boldsymbol{L}}
\newcommand{\bu}{\boldsymbol{u}}
\newcommand{\bLambda}{\boldsymbol{\Lambda}}
\newcommand{\trans}{^{\rm\scriptsize T}}
\newcommand{\var}{\mathrm{var}}\\\newcommand{\bA}{\boldsymbol{A}}
\newcommand{\bB}{\boldsymbol{B}}
\newcommand{\bC}{\boldsymbol{C}}
\newcommand{\bD}{\boldsymbol{D}}
\newcommand{\bG}{\boldsymbol{G}}
\newcommand{\bI}{\boldsymbol{I}}
\newcommand{\bM}{\boldsymbol{M}}
\newcommand{\bP}{\boldsymbol{P}}
\newcommand{\bS}{\boldsymbol{S}}
\newcommand{\bU}{\boldsymbol{U}}
\newcommand{\bW}{\boldsymbol{W}}
\newcommand{\bX}{\boldsymbol{X}}
\newcommand{\bY}{\boldsymbol{Y}}
\newcommand{\bZ}{\boldsymbol{Z}}
\newcommand{\cotp}{\textcolor[RGB]{48,209,88}{TP}}
\newcommand{\cotn}{\textcolor[RGB]{100,210,255}{TN}}
\newcommand{\cofp}{\textcolor[RGB]{94,92,230}{FP}}
\newcommand{\cofn}{\textcolor[RGB]{191,90,242}{FN}}\\\newcommand{\numcotp}{\textcolor[RGB]{48,209,88}{50}}
\newcommand{\numcotn}{\textcolor[RGB]{100,210,255}{30}}
\newcommand{\numcofp}{\textcolor[RGB]{94,92,230}{10}}
\newcommand{\numcofn}{\textcolor[RGB]{191,90,242}{10}}
\DeclareMathOperator*{\argmin}{arg\,min}\end{aligned}\end{align} \]
CNN 基本模块与维度传播:参考答案
返回正文练习 · 返回答案索引
说明
以下答案与正文10道题逐题对应。推导题给出主要步骤;编程和实验题给出参考程序和检查方法,并说明结果适用于哪些条件。
各层维度依次为 \(m\times8\times32\times32\)、\(m\times8\times16\times16\)、\(m\times16\times16\times16\)、\(m\times16\)、\(m\times10\)。第一卷积参数量为 \(8[3(3)(3)+1]=224\),第二卷积为 \(16[8(3)(3)+1]=1168\),线性层为 \(10(16+1)=170\),总计 \(224+1168+170=1562\)。池化与全局平均池化没有可训练参数。
第一卷积后 \(r_1=1+(3-1)(1)=3\)、\(j_1=1\);池化后 \(r_2=3+(2-1)(1)=4\)、\(j_2=2\);第二卷积后 \(r_3=4+(3-1)(2)=8\)、\(j_3=2\)。因此最后一个特征位置覆盖输入上的 \(8\times8\) 区域,相邻特征中心在输入上相隔 2 个像素。边界填充会使部分感受野落到填充值上,但不改变理论跨度。
四个窗口分别是左上、右上、左下、右下的 \(2\times2\) 块。最大池化输出为 \(\begin{bmatrix}6&8\\14&16\end{bmatrix}\);平均池化输出为 \(\begin{bmatrix}3.5&5.5\\11.5&13.5\end{bmatrix}\)。两种运算输出维度均为 \(2\times2\)。
一个固定窗口的最大池化只依赖元素集合的最大值,排列不会改变该最大值,所以输出不变。例如一维输入 \([0,1,0,0]\) 用大小 2、步幅 2 最大池化得到 \([1,0]\);向右平移并以 0 填充得到 \([0,0,1,0]\),池化结果为 \([0,1]\)。输出发生位置变化,若采用裁剪边界还可能丢失响应,因此局部排列不变不能被解释为全局平移不变。
模型和跟踪器可利用虚拟前向自动确定线性层输入:
class SmallCNN(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 8, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(8, 16, 3, padding=1), nn.ReLU(), nn.AdaptiveAvgPool2d(1))
with torch.no_grad():
width = self.features(torch.zeros(1, 3, 32, 32)).flatten(1).shape[1]
self.classifier = nn.Linear(width, 10)
def forward(self, x):
return self.classifier(self.features(x).flatten(1))
trace = []
def hook(module, inputs, output):
trace.append((module.__class__.__name__, tuple(inputs[0].shape),
tuple(output.shape), sum(p.numel() for p in module.parameters())))
只给叶子模块注册钩子,可避免父模块与子模块重复计数。
按输出尺寸公式逐层得到 \(32,16,16,1\) 的空间变化,与钩子记录逐项比较;批次轴应始终为 \(m\)。手工参数量 1562 必须与框架总数完全相等,而不是近似相等。若维度不一致,先检查 NCHW 顺序、填充、步幅和 flatten 起始轴;若参数不一致,检查偏置及分类输出层输入维度。
用 \(m=1\) 与 \(m=7\) 进行前向传播,除第 0 轴外的维度应相同;空间尺寸只要能通过两次卷积与一次池化就应得到合法输出;输入通道不是 3 时应报错;AdaptiveAvgPool2d(1) 与沿高度和宽度求均值的结果一致。完成一次交叉熵后向传播后,每个 requires_grad 参数都有相同维度的梯度,并且 isfinite 的检查结果应为真。
MLP 与 CNN 应使用相同的数据划分、预处理方法、随机种子和更新次数。两个模型在验证集上尝试相同数量的学习率,并为每个学习率使用相同的训练量。CNN 能利用局部连接和权重共享,在图像任务上通常可以用较少参数取得较好的泛化结果;MLP 的矩阵运算在较小输入上也可能运行得较快。哪个模型预测更准确、运行更快,应根据本题实际测量的结果判断。表中报告测试指标的均值与标准差、训练秒数、固定批量预测时间、实际参数量及峰值内存。
三组保持下采样位置与输出维度一致;步幅卷积会增加可训练参数和乘加量,最大池化与平均池化没有参数。各组使用相同的数据划分、随机种子和训练量,并采用相同的方法选择学习率等超参数,只改变下采样方法。报告任务指标、训练时间、固定批量预测时间、参数量、乘加量及峰值内存。最大池化的梯度较稀疏,平均池化会平均分配信息,步幅卷积能够学习下采样方法;哪一种更好取决于具体数据。
宽度翻倍会使相邻卷积层参数量和计算量增长快于线性比例,而特征图内存近似随通道数增长。每组使用相同划分、种子、优化器和更新次数,报告测试性能及波动、训练时间、参数量与峰值内存。若更宽网络没有改善性能,应检查样本量、正则化和训练是否充分;不能只因参数更多就认定模型更好。