神经网络训练基础#

全连接神经网络卷积神经网络中我们学习了如何搭建神经网络架构。但知道"建什么"不等于知道"怎么训练"——就像有了一辆车不等于会开车。本节我们将从梯度下降与优化算法反向传播算法的理论出发,掌握让神经网络真正"学会"的实战技巧。

训练的本质:从数据到能力#

想象你在教小孩认数字。你不会只给他看一遍卡片就指望他记住,而是需要:

  • 反复练习:同一组卡片看很多遍(多轮训练)

  • 及时反馈:猜对了表扬,猜错了纠正(计算损失)

  • 循序渐进:从简单到复杂,调整学习节奏(学习率调度)

  • 防止死记:确保他理解数字的本质,不只是记住卡片(防止过拟合)

神经网络训练完全遵循同样的逻辑。梯度下降与优化算法告诉我们沿着梯度方向更新参数,但实践中还有大量细节需要把握。


核心训练概念#

在深入之前,我们需要统一几个基本概念:

Epoch(轮次):完整遍历整个训练数据集一次。就像把整副卡片从头到尾看一遍。MNIST有60,000张训练图片,一个epoch就是看完全部60,000张。

Batch(批次):一次更新参数时使用的样本集合。如果一次看一张就更新,效率太低;如果看完60,000张才更新,内存可能不够。Batch Size就是每批的样本数,常用32、64、128等2的幂次。

Iteration(迭代):完成一个批次的训练。一个epoch包含的迭代次数 = 总样本数 ÷ Batch Size。

备注

MNIST训练示例

  • 总训练样本:60,000张

  • Batch Size:64

  • 每epoch的迭代次数:60,000 ÷ 64 ≈ 938次

  • 训练10个epoch:总共迭代9,380次,更新参数9,380次


损失函数的选择#

损失函数中我们讨论了不同任务的损失函数设计。在实战中,选择主要取决于任务类型

任务类型

推荐损失函数

为什么

回归

MSE / MAE

直接衡量数值偏差

二分类

BCE Loss

衡量概率校准程度

多分类

CrossEntropy

结合Softmax,梯度更稳定

MNIST的交叉熵

MNIST是10类分类,使用交叉熵损失

\[ \mathcal{L} = -\sum_{c=1}^{10} y_c \log(p_c) \]
  • \(y_c\):真实标签的one-hot编码(目标类别为1,其余为0)

  • \(p_c\):Softmax输出的概率

为什么不用MSE? 分类任务的输出是概率分布,交叉熵对这种"分布间的差异"更敏感,且避免了梯度消失问题(见反向传播算法)。


过拟合与欠拟合:学习的两种失败#

训练神经网络就像准备考试——有两种典型的失败模式:

欠拟合:学得太少#

想象一个学生只翻了翻课本,没做练习题就去考试:

  • 训练时表现就不好(训练损失高)

  • 考试时更差(验证损失也高)

  • 原因:模型太简单,没能捕捉数据的基本规律

  • 解决:增加网络深度、训练更长时间、降低正则化强度

过拟合:死记硬背#

另一个学生把所有练习题都背下来了:

  • 做练习题时几乎全对(训练损失很低)

  • 遇到新题就不会(验证损失高,差距大)

  • 原因:模型记住了训练数据的噪声,而非学习通用规律

  • 解决:使用正则化、早停、数据增强、降低模型复杂度

Figure made with TikZ

模型复杂度与泛化性能

图中的"最佳点"是我们追求的目标:足够复杂的模型捕捉规律,但不至于过拟合。找到这个点需要验证集——用训练集学习,用验证集调参,最后用测试集评估。


数据划分:训练集、验证集、测试集#

为什么需要三组数据?

  • 训练集:学习参数(权重和偏置)

  • 验证集:选择超参数(学习率、网络结构、正则化强度)

  • 测试集:最终评估(只能用一次!)

警告

测试集的禁忌

测试集只能用于最终报告,绝不能用来调参或选择模型。否则就像考试时偷看答案——分数虚高,真实能力被高估。

MNIST的标准划分:60,000训练 + 10,000测试。实践中,我们会从训练集中分出10%(6,000张)作为验证集,剩下54,000张真正用于训练。


正则化:防止死记硬背的四种方法#

正则化的核心思想:限制模型的"记忆能力",逼迫它学习"理解能力"

为什么需要限制?想象一个拥有超强记忆力的学生——他可以背下所有练习题答案,考试时遇到原题全对,但稍微变化就不会。神经网络也有这种"过强记忆"的能力,特别是参数量大时。正则化就是防止这种"死记硬背"。


1. L2正则化(权重衰减):强制"粗笔画"#

核心洞察:权重大小决定决策边界的"粗细"

想象用画笔画画:

  • 细笔画(大权重):可以画出非常锐利、复杂的边界,精确勾勒每个训练样本的细节——就像用0.5mm的针管笔,能画出极细的线条

  • 粗笔画(小权重):只能画出平滑、模糊的轮廓,捕捉大体形状——就像用毛笔,线条自然柔和

神经网络的决策边界也是由权重决定的。大权重让边界变得"尖锐",可以"钻牛角尖"去拟合每个训练点;小权重让边界保持"平滑",只能学习通用的模式。

为什么L2惩罚能实现这一点?#

L2正则化在损失函数中加入权重的平方和:

\[ \mathcal{L}_{\text{total}} = \mathcal{L}_{\text{original}} + \frac{\lambda}{2} \sum_{i} w_i^2 \]

关键洞察:平方惩罚对大权重的"惩罚力度"远大于小权重。

权重值

原始损失惩罚

平方惩罚

相对增加

0.1

1

0.01

1%

1.0

1

0.5

50%

10.0

1

50

5000%

结果:优化器会发现,与其让少数权重变得很大(承担巨额平方惩罚),不如让所有权重都保持较小。这就像税收——平方税率对大收入者更严厉,促使财富分布更均匀。

# PyTorch中的L2正则化(weight_decay)
optimizer = torch.optim.Adam(
    model.parameters(),
    lr=0.001,
    weight_decay=1e-4  # λ = 0.0001
)

为什么有效? 小权重的网络更"保守",不会为了拟合某个训练样本的噪声而剧烈调整输出。它必须找到更通用的规律,才能在保持权重小的同时降低原始损失。


2. Dropout:随机"罢工"迫使协作#

Dropout 由 Srivastava 等人在 2014 年提出 [SHK+14],是防止神经网络过拟合的有效方法。

核心洞察:随机"点名"防止依赖"学霸"

想象一个班级有50人,老师提问时总是叫同一个"学霸"回答:

  • 学霸越来越厉害(某些神经元权重变得极大)

  • 其他同学从不思考(其他神经元权重趋于0)

  • 结果:班级极度依赖学霸,一旦学霸生病(过拟合到新数据),全班表现崩盘

Dropout就像随机点名:每次提问随机抽一半同学,学霸也可能被抽中休息。

  • 后果:每个人都必须准备好回答问题

  • 结果:知识必须在全班分布式存储,形成冗余表示

为什么冗余表示能防止过拟合?#

过拟合的本质是"记忆"——模型记住了训练数据的具体特征(包括噪声)。如果知识只存储在少数几个神经元中,这些神经元就会"死记硬背"训练样本。

Dropout迫使知识分散存储:

  • 识别"横线"的特征不是由某1个神经元专门负责,而是由10个神经元共同分担

  • 即使其中5个被"dropout"了,剩下5个还能大致识别横线

  • 每个神经元都不能"偷懒"记忆特定样本,必须学习通用特征

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 256)
        self.dropout = nn.Dropout(0.5)  # 50%的dropout
        self.fc2 = nn.Linear(256, 10)
        
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.dropout(x)  # 训练时随机丢弃,测试时自动关闭
        return self.fc2(x)

测试时为什么关闭Dropout? 训练时的随机丢弃相当于训练了多个"子网络"(2^N种可能的组合)。测试时我们使用完整网络,相当于**集成(ensemble)**了所有这些子网络的预测,取平均——这通常比任何单个子网络更稳定。


3. 早停法:在"最佳点"刹车#

核心洞察:训练就像在山谷中行走,不要越过谷底

想象你在一个山谷中(损失函数的Loss Landscape),从高处往低处走(梯度下降):

初期:你在宽阔的山谷顶部,大步流星地向谷底走去——训练损失和验证损失都在下降,方向基本一致。

中期:你接近谷底,步伐变小,损失下降变慢——但仍朝着正确的方向微调。

后期:如果你继续走,可能会越过谷底,走上另一侧山坡——训练损失还在下降(因为你更贴合训练数据),但验证损失开始上升(因为你开始"钻牛角尖",拟合了训练集的噪声)。

Figure made with TikZ

早停法:在谷底停止,不要越过

为什么验证损失上升意味着过拟合?#

训练损失只衡量模型在训练数据上的表现。当你训练太久,模型开始"记住"训练数据中的噪声——那些只存在于训练集、不存在于真实世界的随机波动。

验证集是独立的数据,不包含训练集的噪声。所以当模型开始拟合训练噪声时,它在验证集上的表现反而会变差。

早停法的本质:在"学习真实规律"和"记忆训练噪声"的临界点停止训练。

工程实现:框架中的早停

社团框架将早停封装为一行参数——--patience 5 表示验证损失连续 5 轮不下降即停止训练。详见实验管理:从手动记录到自动追踪


4. 数据增强:免费的"新数据"#

核心洞察:更多数据帮助区分"本质"与"偶然"

想象你要学会"识别圆形":

  • 只看过1个圆 → 你可能以为"红色、半径5cm、在画面中央"才是圆的本质特征

  • 看过100个圆(不同颜色、不同大小、不同位置)→ 你意识到"到中心点距离相等"才是本质,颜色和大小只是偶然特征

过拟合的本质是"将偶然当成必然"——把训练数据中的特定属性(如"这个位置的像素总是白色")当成了类别的本质特征。

数据增强通过创造人工变体,让模型看到更多样的样本:

原始样本

增强变体

学到的规律

数字"3"在中央

数字"3"向左移2像素

位置不重要,形状才重要

数字"3"正常大小

数字"3"放大10%

大小不重要,比例才重要

数字"3"竖直

数字"3"轻微旋转

方向不重要,拓扑结构才重要

train_transform = transforms.Compose([
    transforms.RandomRotation(10),      # ±10度旋转
    transforms.RandomAffine(0, translate=(0.1, 0.1)),  # ±10%平移
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

为什么有效?#

数据增强迫使模型学习不变性(invariance)——哪些特征在变换下保持不变。模型发现:

  • 无论"3"在什么位置,它都是"3"

  • 无论"3"多大,它都是"3"

  • 无论"3"是否倾斜,它都是"3"

因此,模型必须抓住本质特征(形状、拓扑结构),而不能依赖偶然特征(位置、大小、角度)。这些偶然特征在不同样本间变化,无法作为可靠的分类依据。


如何选择正则化方法?#

全连接神经网络中我们讨论了全连接网络的参数量爆炸问题,卷积神经网络中则看到CNN如何通过归纳偏置减少参数。但无论架构如何,正则化都是必需的——它是防止模型"死记硬背"的最后防线。

方法

使用场景

实现难度

早停法

总是使用

⭐ 最简单

L2正则化

几乎所有情况

⭐ 添加一个参数

Dropout

深层网络、过拟合严重时

⭐⭐ 需调整比例

数据增强

图像、语音等数据

⭐⭐ 需设计变换

初学者路径

  1. 第一步:只用早停法(零成本,必做)

  2. 第二步:加上L2正则化(weight_decay=1e-4)

  3. 第三步:添加Dropout(0.3-0.5)

  4. 第四步:尝试数据增强


批量大小与学习率#

批量大小的权衡#

批量大小

优点

缺点

小(32-64)

泛化性好,内存占用低

梯度噪声大,训练不稳定

大(256+)

梯度准确,可并行加速

可能陷入尖锐局部最优,内存需求大

直觉:小批量就像用少量样本"试探"方向,虽然每次方向不太准,但不容易被困住;大批量像精准测量,但可能错过更好的路径。

这与梯度下降与优化算法中讨论的"噪声帮助逃离局部最优"原理一致——适度的梯度噪声反而有助于找到更好的解。

学习率调度#

固定学习率不一定是最佳选择。回顾梯度下降与优化算法中的"下山"类比——刚开始你可能希望大步快走,接近谷底时需要小步微调。常见策略:

  • 预热(Warmup):刚开始用较小学习率,逐渐增加——避免初期震荡(防止"一脚踩空")

  • 衰减(Decay):训练后期逐渐减小学习率——精细化调整(在谷底附近小心探索)

  • 余弦退火(Cosine Annealing):周期性变化——帮助逃离局部最优(周期性地"震荡"寻找更好的山谷)

# 余弦退火调度
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
    optimizer, T_max=100  # 100个epoch为一个周期
)

# 训练循环中
for epoch in range(num_epochs):
    train(...)  # 训练
    scheduler.step()  # 更新学习率

工程实现:框架中的调度器

社团框架内置 5 种调度器(Step / Cosine / Plateau / Exponential / None),CLI 参数 --scheduler cosine --scheduler-t-max 50 即可启用。详见配置系统:从硬编码到配置文件


训练监控指标#

有效的训练需要实时监控:

指标

正常趋势

异常信号

训练损失

逐渐下降

不降或震荡

验证损失

先降后平

上升(过拟合)

训练准确率

逐渐提高

停滞在低位(欠拟合)

验证准确率

跟踪训练准确率

与训练差距大(过拟合)

关键观察

  • 训练损失 \(<\) 验证损失:正常现象

  • 训练损失 \(\ll\) 验证损失:严重过拟合,加强正则化

  • 两者都高:欠拟合,增加模型容量或训练时间

回顾本节讨论的过拟合与欠拟合现象——这些监控指标就是诊断工具,帮助你在训练过程中实时判断模型状态。

工程实现:框架中的自动监控

社团框架每轮自动记录损失、准确率、学习率、训练速度,训练结束后自动绘制 4 面板训练曲线图(runs/expN/training_curves.png),无需手动记录和绘图。详见实验管理:从手动记录到自动追踪


总结:训练检查清单#

开始训练前,确认以下事项:

检查项

建议

框架实现

参考章节

数据划分

训练/验证/测试 = 70%/15%/15% 或类似比例

数据集类内置划分

本节"数据划分"部分

损失函数

分类用CrossEntropy,回归用MSE

模型自带 get_criterion()

损失函数

优化器

Adam [KB15] 是默认首选,学习率0.001

--optimizer adamw

梯度下降与优化算法

正则化

至少使用早停法和L2正则化

--patience + --weight-decay

本节"正则化"部分

批量大小

从64或128开始,根据内存调整

--batch-size 64

本节"批量大小"部分

监控指标

同时关注训练和验证的表现

自动记录并绘制曲线

本节"训练监控指标"部分

本节将梯度下降与优化算法反向传播算法的理论转化为实践——从选择损失函数、设计正则化策略,到监控训练过程。现在你已经掌握了让神经网络"学会"而不是"记住"的完整工具箱。


下一步#

掌握了训练基础后,你可以在使用训练框架中用社团框架将本节的理论转化为工程实践——配置 --optimizer--scheduler--patience 一行命令验证不同训练策略的效果。

CNN 消融研究:理解卷积神经网络各组件的作用中,我们还将通过消融实验量化 CNN 各组件对性能的影响,用数据回答:

  • 哪些训练技巧是"雪中送炭",哪些是"锦上添花"?

  • 不同正则化方法的实际贡献有多大?

  • 如何通过控制变量法做出科学的设计决策?

从"知道怎么训练"进化到"知道怎么科学地验证训练方案"!


参考文献#

[KB15]

Diederik P Kingma and Jimmy Ba. Adam: a method for stochastic optimization. In International Conference on Learning Representations. 2015.

[SHK+14]

Nitish Srivastava, Geoffrey Hinton, Alex Krizhevsky, Ilya Sutskever, and Ruslan Salakhutdinov. Dropout: a simple way to prevent neural networks from overfitting. The journal of machine learning research, 15(1):1929–1958, 2014.

贡献者与修订历史

查看详细修订记录
  • 0cdb1e4 2026-04-29 - Heyan Zhu: feat: add model-serving chapter and update related content
  • b20ef3e 2026-04-28 - Heyan Zhu: docs: update pytorch practice section with detailed explanations and code examples
  • 59126f4 2026-04-26 - Heyan Zhu: docs(math-fundamentals): update content structure and add citations
  • cec393d 2025-12-11 - Heyan Zhu: docs: partially complete migration and restructure course materials
  • 0c291d7 2025-12-10 - Heyan Zhu: docs: restructure course materials and add new content