AlexNet 与 CIFAR-10 实现:参考答案

目录

\[ \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} \]

AlexNet 与 CIFAR-10 实现:参考答案#

返回正文练习 · 返回答案索引

说明#

以下答案与正文10道题逐题对应。推导题给出主要步骤;编程和实验题给出参考程序和检查方法,并说明结果适用于哪些条件。

  1. 首层输出为 \(\lfloor(32-11)/4\rfloor+1=6\)⁠,第一次池化输出为 \(\lfloor(6-3)/2\rfloor+1=2\)⁠。填充 2 的 \(5\times5\) 卷积仍输出 2;第二次 \(3\times3\) 池化要求输入至少为 3,但当前只有 2,公式给出 \(\lfloor(2-3)/2\rfloor+1=0\)⁠,因此该步非法。这说明结构适配不能只修改最终线性层。

  2. 空间尺寸链为 \(227\rightarrow55\rightarrow27\rightarrow27\rightarrow13\rightarrow13\rightarrow13\rightarrow13\rightarrow6\)⁠。其中三个 \(3\times3\) 卷积都使用填充 1,故保持 13;最后池化得到 6。于是经典展平维度为 \(256(6)(6)=9216\)⁠。一些资料把输入概括为约 \(224\times224\)⁠,通常会同时采用不同的裁剪、首层填充或边界处理约定;计算时必须先明确整套配置,不能把 \(224\times224\) 输入与本题的无填充 \(227\times227\) 尺寸链混用。

  3. 第一线性层参数量为 \(4096[256(6)(6)+1]=37752832\)⁠,第二层为 \(4096(4096+1)=16781312\)⁠,第三层为 \(10(4096+1)=40970\)⁠,合计 54575114。仅分类输出层就超过五千万参数,因此其权重存储和矩阵运算可能超过卷积部分;缩小空间尺寸或用全局平均池化可显著减少该成本。

  4. 训练输出为 \((1,0,1,0)\odot(2,0,-4,6)/0.5=(4,0,-8,0)\)⁠。对随机掩码取条件期望时,每个位置以概率 0.5 保留并放大 2 倍,因此期望仍为 \((2,0,-4,6)\)⁠。评估模式不采样掩码也不再缩放,直接输出原激活。

  5. 适配网络可以保留“多层卷积 + 大分类输出层”的思想,但匹配小输入:

    class AlexNetCIFAR(nn.Module):
        def __init__(self, classes=10):
            super().__init__()
            self.features = nn.Sequential(
                nn.Conv2d(3, 64, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
                nn.Conv2d(64, 192, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
                nn.Conv2d(192, 256, 3, padding=1), nn.ReLU(),
                nn.Conv2d(256, 256, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
                nn.AdaptiveAvgPool2d((2, 2)))
            self.classifier = nn.Sequential(nn.Dropout(0.5), nn.Linear(256*2*2, 512),
                                            nn.ReLU(), nn.Dropout(0.5), nn.Linear(512, classes))
        def forward(self, x):
            return self.classifier(self.features(x).flatten(1))
    

    也可用虚拟前向替代手工写出的 256*2*2

  6. 可以在各层完成计算时记录其输出,按照 \(m\times d_C^{[l]}\times d_H^{[l]}\times d_W^{[l]}\) 的顺序与公式逐层核对。使用 next(model.parameters()).device == input.device 检查模型与输入位于同一设备;训练模式下,由于 Dropout 的随机屏蔽,同一输入的多次输出通常不同,评估模式下则应相同。参数量可把手工逐层求和的结果与 sum(p.numel()) 对照。若存在 BatchNorm 或 Dropout,维度与数值检查应明确使用 train 还是 eval 模式。

  7. 原始结构输入 32 应在第二次池化前被维度检查拒绝;适配结构对 \(m=1,8\) 均输出 \(m\times10\)⁠;train()eval() 的 Dropout 行为符合第 4 题;模型与输入移动设备后输出设备相同;交叉熵后向传播后,每个参数梯度都应具有正确维度并且是有限数值。没有 GPU 时可以跳过 GPU 设备检查,不能把环境缺少 CUDA 当作模型错误。

  8. 两种方案使用相同的原始数据划分、随机种子和更新次数,并在验证集上尝试相同数量的优化器设置;但是,放大输入的方案每一步所需的计算量远大于使用原始尺寸的方案。报告测试指标及其波动、训练秒数、固定批量预测时间、参数量、乘加量和峰值内存。放大输入不会创造新的图像细节,却可能更接近经典 AlexNet 的尺寸变化过程;适配原始图像尺寸的结构通常计算效率更高。由于输入大小和网络结构同时改变,结果只能说明这两个具体方案在本题数据与硬件上的差异,不能单独说明某一项改动的作用。

  9. 三组只改变 Dropout 概率,复用划分、种子、初始化、批次顺序和更新次数。适度 Dropout 可能减小训练—验证差距,过强会减慢拟合;评估时 Dropout 关闭,所以参数量和预测计算图相同。报告任务指标、差距、训练时间、固定批量预测时间及峰值内存;计时应多次重复,不能把随机波动当作推断效率差异。

  10. LRN 没有常见的可训练尺度参数,BatchNorm 增加逐通道尺度与平移并维护运行统计量。三组固定数据、种子、更新次数、增强和验证预算,报告测试性能、训练与固定批量预测计时、参数量和峰值内存。LRN 是 AlexNet 的历史组件,BatchNorm 属于现代训练配方;若后者更好,只能说明当前数据与训练设置下的比较结果,不能把修改后的网络称为原版 AlexNet。