深度学习实验实践指南:参考答案

目录

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

深度学习实验实践指南:参考答案#

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

说明#

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

  1. 少量且容易区分的训练样本通常比较容易学习。如果模型不能几乎完全正确地预测这些样本,应优先检查输入数据与标签是否对应、数组维度是否正确、损失函数是否合适、参数是否真正得到更新,以及模型是否具有足够的学习能力。不过,这项检查只表明模型能够学习当前给出的少量训练样本。例如,数据处理程序可能错误地提前使用了验证集或测试集的信息,但模型仍能通过检查;验证样本与验证标签可能没有正确对应,这也不会影响模型学习训练样本;参数很多的模型还可能只是记住了少量训练样本,却不能正确预测新数据。因此,通过这项检查不能证明整个实验流程完全正确,也不能保证模型在新数据上表现良好。

  2. 无动量时 \(\Delta\btheta=-0.02\nabla\mathcal J\)⁠,故更新范数为 \(0.02(5)=0.1\)⁠,相对更新量为 \(0.1/20=0.005\)⁠,即 \(0.5\%\)⁠。单步数值没有通用的好坏阈值;应结合损失、梯度范数和多步变化观察。持续接近 0 可能表示学习过慢或梯度断开,持续过大且损失剧烈波动可能表示学习率过大。

  3. 验证损失最小的是第 2 轮,应保存该轮。最后一轮损失比最佳轮高 \(0.62-0.55=0.07\)⁠,准确率低 \(0.76-0.73=0.03\)⁠,即 3 个百分点。选择规则必须在观察测试结果前确定;若用测试指标改选轮次,测试集就参与了模型选择,最终测试结果会偏乐观。

  4. 处理一个训练批次的平均时间为 \(40/200=0.2\) 秒。完成一次固定批量预测的平均时间为 \(2/100=0.02\) 秒,即 20 毫秒。设备首次编译、缓存和异步执行都会影响计时,所以各方案必须采用相同预热次数、必要的设备同步、固定批量和重复次数。

  5. 检查器应在更新前后分别记录状态:

    def check_step(x, y, loss, model, before, allowed_labels, step):
        if not np.isfinite(np.asarray(x)).all():
            raise FloatingPointError(f"step={step}: 输入非有限")
        if not set(np.asarray(y).tolist()) <= set(allowed_labels):
            raise ValueError("标签超出允许集合")
        if not torch.isfinite(loss):
            raise FloatingPointError(f"step={step}: 损失非有限")
        grad2 = sum((p.grad.detach() ** 2).sum() for p in model.parameters()
                    if p.grad is not None)
        delta2 = sum(((p.detach() - q) ** 2).sum()
                     for p, q in zip(model.parameters(), before))
        param2 = sum((q ** 2).sum() for q in before)
        return {"grad_norm": grad2.sqrt().item(),
                "relative_update": (delta2 / param2.clamp_min(1e-30)).sqrt().item()}
    

    异常处理还应保存步号、批次索引、配置和随机数生成器状态。

  6. 标签错位应首先表现为小样本无法稳定过拟合或标签—样本一致性测试失败;过大学习率应触发损失/梯度非有限或相对更新量异常;未切换评估模式可通过对同一样本改变同批伙伴后预测变化来发现;NaN 输入必须在前向前被有限性断言截获。每个故障只改变一个因素,测试先确认错误版本稳定失败,再修复并运行全部旧测试。

  7. 三个学习率共享同一批次顺序、初始化种子和更新次数。较小值可能稳定但达到阈值较慢,较大值可能更快也可能振荡或发散;应保留失败运行。报告多种子测试指标、达到阈值时间、总训练秒数、固定批量预测时间、参数量和峰值内存。学习率不改变模型结构,因此参数量和推断成本原则上相同;若实测差异明显,应增加重复计时并检查设备状态。

  8. 先明确是固定总样本数还是固定更新次数;两种预算回答的问题不同,不能混用。批量大小会影响硬件利用率、峰值内存、更新次数、梯度噪声和最终指标。结果表应给出任务指标均值与标准差、总训练时间、相同固定批量的预测时间、参数量和峰值内存。模型结构不变时参数量及推断图相同,预测计时不应使用各自的训练批量。

  9. 三种流程共享同一最大轮数、验证频率和选择指标。使用最后一轮可能错过泛化最好的阶段;加载最佳检查点不节省训练,但通常避免性能回退;提前停止还能减少实际轮数,却可能因验证噪声或耐心值过小而过早结束。应报告实际训练轮数与秒数、测试指标、固定批量预测时间、参数量和峰值内存。三种流程最终网络结构相同,预测成本应近似,主要权衡在任务性能和训练成本。