本节摘要:把第 2–5 章的零件真正装进一个完整排查流程:先用一个小网络跑通拿到基线,区分欠拟合与过拟合两大分支,再按"容量 / 时长 / 正则 / 调度 / 优化器"顺序有序地调。本节用一个图像分类案例从欠拟合一路调到收敛,给出每一步的信号与动作。
前面四节分别讲了调度、正则、裁剪、调参,但做项目时你不会一个一个零件孤立用——你要把整台车开起来,用一套有序的流程边看仪表边修。这一节就是把"实战调试"写成可照做的套路。
调试的第一铁律:用一个尽量朴素、确定能跑通的配置拿到"能动的基线",再往上叠东西。 别一上来就上 Adam、Dropout、余弦调度大全套——那样出了问题你根本分不清是哪一环。
最小可行基线长这样:
这个基线的作用是给你一个"会不会是代码/数据错了"的基准。很多所谓"不收敛",其实在基线阶段就暴露了:数据喂错、标签错位、NaN 早现。
跑起来之后,紧盯训练损失与验证损失两条曲线的相对走势,先判断大方向:
这一步不跳到细节,先立起大方向。
把第 5 章的装配件串成一张决策图,从上往下走。
工程经验:一步只动一个变量的原则——每次改一个旋钮、看两条曲线,效果才归因清楚。同一次改 5 个旋钮,最后好也不知道好在哪、坏也不知道坏在哪。
背景:你在训一个小型图像分类,丢进一个 3 层小卷积,希望验证精度上 80%。初始曲线:训练损失约 0.9 怎么都降不动,验证也卡在 0.9 上下。
第一步:跑通基线确认能学。 用一个小划分的 500 张子集,关掉一切正则,很快训练损失砸到 0.2 以下——证明代码和数据没毛病,问题在容量不够。
第二步:加容量。 卷积通道从 16 加到 64,再加一层,训练损失下降了,可验证没跟上来,出现下述现象。
第三步:区分方向。 现在训练降得动、验证反弹 → 进入过拟合分支。加 L2 系数 1e-4,再试 Dropout 0.3 于全连接前,验证跟上了。
第四步:换调度求极限。 换成余弦退火,让后期的学习率平滑收小,验证精度从 80.1 爬到 82.3。
第五步:留层确认。 调优时用的都是验证集,最后切出一层干净的测试集跑一遍,确认 82.3 不是"挑出来的假高点"。
结果:从 0.9 卡住到最终 82.3%,全程 + 每一步的改动都能说出理由——这就是"有序调试"胜过"乱改碰运气"的地方。
这个案例里每一步的决策,你都可以回指到前几章:容量(第 2–4 章表达力)、正则(5.2)、调度(5.1)、验证分层(5.4)。
| 症状 | 最可能的元凶 | 该查哪 |
|---|---|---|
| 损失压根不降 | 数据/标签/学习率太低 | 基线、选型 |
| NaN | 梯度爆炸/初始化差 | 5.3 裁剪 |
| 训练降验证不降 | 过拟合 | 5.2 正则 |
| 验证降训练也低 | 正常偏欠拟合 | 加容量/时长 |
| 损失卡平台 | 学习率调度缺失 | 5.1 |
💡 关键直觉:调试不是"找最优参数的一根头发丝",而是把"能学 → 学得会 → 不过拟合地全学会"这三道关逐关打通。每道关有各自的零件,逐关过才是最快的路。
前面几节讲的基线、归因、逐关背后,其实有一根共同的骨头——日志与版本纪律。 调试最怕"改了五处、三处不记得、两处没说清",那最后好也不知道好在哪。给你两件顺手可用的工具:
看起来像"额外负担",但它是让第 5 章这整套零件"可复现、可归因"的地基——没有它,你有再好的零件也分不清哪颗螺丝起了作用。
这一节的设计几乎是围绕"一次只动一个"展开的,因为它不只在调参上有用,在跨章节诊断时同样成立:当你不确定是调度、正则还是容量的问题时,每动一个就看曲线,你能把每个旋钮的单独贡献如实记录下来;一旦你同时动了三个,出场顺序根本无从谈起。
所以再强调一遍——"改一个、看两条曲线、记一句结论、再改下一个"是第 5 章最值钱的纪律。 它能让你在一个下午的调试里,获得一叠"每个旋钮都有据可查"的干净证据,而不是一团"好像调对了"的运气。
整车在试驾场跑顺了。最后一章把整条主线收束回"天平",看这些技巧在整个学习体系里的分量,以及它们开往前沿的方向。