训练神经网络的实用技巧:优化、泛化与模型架构全解析 Hung-yi Lee 2025-11-14

前言:理解训练技巧的核心框架

今天这堂课旨在向大家介绍在训练类神经网络时会用到的各种技巧。在上一堂课中,我们已经明确了机器学习的三个核心步骤:

  1. 定义损失函数(Loss Function)。
  2. 确定函数的选择范围(模型架构)。
  3. 选择一个最优的函数(优化过程)。

完成这三个步骤训练出模型后,不能立即进行测试,必须先进行验证(Validation)。只有当验证结果足够好时,才能进入测试环节;否则,就需要回到学习的三个步骤中,检查是哪个环节出了问题。

上周我们还探讨了深度学习的基本观念,即所谓的深度学习或类神经网络,本质上是划定一个更大的函数选择范围,从而有机会包含更多样化的函数。

今天,我们将介绍一系列在训练类神经网络时常用的技巧。由于内容繁多且时间有限,许多技术可能只会以较快的节奏带过,但我会指出在过去课程的哪些部分可以找到更详细的资料。如果你没有训练类神经网络的经验,今天的内容可能会有些挑战。

本堂课的重点是,每当你听到一个关于训练类神经网络的新方法或技巧时,都应该问自己一个问题,并尝试填写下面的表格:

方法/技巧 改变了哪个步骤? (1, 2, or 3) 带来了什么好处? (优化/泛化)

首先,这个方法改变了机器学习三个步骤中的哪一个?它是一个新的损失函数,还是一个不同的网络架构(即划定了不同的选择范围),抑或是一种更高效的优化算法?

其次,这个方法到底带来了什么好处?很多人在介绍新方法时只会说“这个方法好”,但“好”可以有很多不同的面向。今天课程中提到的好处大致可分为两个方向:

  1. 更好的优化 (Optimization):这意味着我们可以找到更低的训练损失(Training Loss)。
  2. 更好的泛化 (Generalization):这意味着训练损失和验证损失(Validation Loss)更接近,能够有效避免过拟合 (Overfitting) 的发生。

每个方法针对的目标和解决的问题是不同的。因此,当你听到一个新技巧时,必须思考它带来的具体好处是什么,并根据不同情况选择合适的应对方法。

区分优化问题与泛化问题

举例来说,假设你先训练了一个线性模型(Linear Model),发现其损失可以降得很低。接着,你尝试训练一个类神经网络,却发现它的损失降得不如线性模型低。有些人会不假思索地称之为“过拟合”,这是不准确的。

如果深度学习模型的训练损失本身就降不下去,这不叫过拟合,而是在优化环节出了问题。深度网络的参数远多于线性模型,理论上它能做到的事情,线性模型也能做到。因此,它的损失至少应该和线性模型一样低,甚至更低。如果你发现深度网络的训练损失无法达到线性模型的水平,那就说明你的优化过程存在问题,此时应选择能强化优化的技巧。

反之,如果你发现训练损失已经足够低,但验证损失却无法随之下降,这才是真正的过拟合。在这种情况下,你才需要选择能够改善泛化的方法。

理解了这一点,今天的课程就没有白费。接下来,我们将系统地介绍一系列与训练类神经网络相关的方法,并按照它们所改变的步骤进行分类,同时指明其设计目标是优化还是泛化。我们将从步骤三开始,逆序进行讲解。

步骤三:优化算法的改进

我们先来回顾一下优化是如何进行的。通常我们使用最简单的梯度下降法 (Gradient Descent),这是一种通过计算参数对损失函数的梯度来迭代更新参数,以寻找损失最小值的优化算法。其中,最原始、不加任何修饰的版本被称为 Vanilla Gradient Descent

梯度下降的流程如下:

  1. 随机初始化一组参数 $\theta_0$。
  2. 计算在 $\theta_0$ 位置的梯度 $g_0$。
  3. 使用学习率(Learning Rate)$\eta$ 更新参数:$\theta_1 = \theta_0 - \eta \cdot g_0$。
  4. 重复此过程,直到梯度变得非常小,参数不再更新为止。

Optimizer:超越当前梯度的智慧

最原始的梯度下降法仅根据当前计算出的梯度来决定更新方向。如果当前梯度为零,更新就会停止。然而,有一系列被称为优化器 (Optimizer) 的技术,它们不仅考虑当前的梯度,还会综合利用从 $g_0$ 到 $g_t$ 的所有历史梯度信息,来共同决定下一步的前进方向。

在 PyTorch 等深度学习框架中,使用这些优化器通常只需在代码中修改一个英文单词。尽管实现简单,但理解其背后的原理至关重要。

学习率的挑战与 Adagrad 的诞生

为什么我们需要优化器?一个主要原因是学习率(Learning Rate)极难调整。学习率设置得太大,参数更新可能会“飞出”损失函数的山谷;设置得太小,更新速度又会极其缓慢。

问题的根源在于,损失函数在不同参数维度上的“地势”变化可能截然不同。例如,在某个方向上梯度很大,需要较小的学习率;而在另一个方向上梯度很小,则需要较大的学习率。传统的梯度下降法对所有参数使用相同的学习率,这显然不是最佳策略。

我们应该因材施教,为每个参数设置不同的学习率。一个直观的想法是:如果某个方向的梯度通常很大,就给它较小的学习率;反之,如果梯度通常很小,就给它较大的学习率。

这个想法催生了 Adagrad (Adaptive Gradient Algorithm),一种自适应学习率的优化器。它通过累积每个参数过去所有梯度的平方和来调整该参数的学习率。具体来说,参数 $\theta$ 的第 $i$ 个维度的更新公式如下: $$ \theta_{t+1, i} = \theta_{t, i} - \frac{\eta}{\sigma_{t,i}} g_{t,i} $$ 其中,$g_{t,i}$ 是在第 $t$ 步时第 $i$ 个维度的梯度,而 $\sigma_{t,i}$ 是从第 0 步到第 $t$ 步所有梯度的平方和的平方根: $$ \sigma_{t,i} = \sqrt{\sum_{j=0}^{t} (g_{j,i})^2} $$ 通过这种方式,梯度历史值越大的参数,其有效学习率就越小。

在实际演示中,使用普通梯度下降法时,学习率设为 0.0001 训练 100 步后进展缓慢,而设为 0.001 则会直接发散。但换用 Adagrad 后,我们可以将初始学习率设得更大(例如 1.0),因为它会自动调整每个参数的学习率。尽管初期更新可能不稳定,但模型很快就能走上正轨,在同样 100 步内达到的效果远超普通梯度下降法。

RMSprop:应对变化的梯度

Adagrad 有一个很强的假设:过去梯度的平均大小可以很好地预测未来。然而,在复杂的损失曲面上,同一个方向的梯度可能时大时小。Adagrad 会累积所有历史梯度,导致其对近期梯度的变化反应迟缓。

为了解决这个问题,RMSprop (Root Mean Square Propagation) 被提了出来。它是一种改进版的 Adagrad,通过引入一个衰减因子 $\alpha$,给予最近的梯度更大的权重。其 $\sigma$ 的计算方式变为一个指数移动平均: $$ \sigma_{t,i}^2 = \alpha \cdot \sigma_{t-1,i}^2 + (1-\alpha) \cdot g_{t,i}^2 $$ 这样,$\sigma$ 就能更及时地反映梯度的近期变化,使得学习率的调整更加灵活。

在一个形如香蕉的 Rosenbrock 函数(一个经典的优化测试函数)上进行测试,Adagrad 在 1000 次迭代后仍离最优点有显著距离。而 RMSprop 在同样步数下,由于能更快地调整学习率,可以走得更远,更接近最终结果。

Momentum:冲出局部最优的动量

除了学习率问题,梯度下降还可能在梯度很小的地方停滞,例如局部最小值(local minima)或鞍点(saddle point)。在现实物理世界中,一个滚下山坡的球因为有动量,并不会在平坦处立即停下。我们可以将动量 (Momentum) 的概念引入优化过程。

Momentum 方法的核心思想是,参数的更新方向不仅取决于当前的梯度,还取决于过去所有梯度的累积。我们将历史梯度的加权平均值记为 $m_t$: $$ m_t = \beta \cdot m_{t-1} + (1-\beta) \cdot g_t $$ 然后,我们使用这个动量 $m_t$ 来更新参数,而不是直接使用梯度 $g_t$: $$ \theta_{t+1} = \theta_t - \eta \cdot m_t $$ 这样,即使当前梯度为零,只要历史动量不为零,参数更新仍会继续,从而有机会“冲”过鞍点甚至一些较浅的局部最小值。

在一个布满局部最小值的 Rastrigin 函数上测试,RMSprop 很快就陷入了一个局部最优并停止更新。而 Momentum 方法则能凭借累积的动量,成功翻越一个又一个“山丘”,最终在全局最优解附近稳定下来。

Adam:动量与自适应学习率的结合

RMSprop 累积的是梯度平方(不考虑方向),用于调整学习率;Momentum 累积的是梯度本身(考虑方向),用于决定更新方向。这两者可以结合吗?当然可以。

将它们结合起来,就得到了 Adam (Adaptive Moment Estimation),这至今仍是深度学习中最常用、最默认的优化器之一。Adam 同时维护了梯度的一阶矩估计(动量)和二阶矩估计(类似 RMSprop 的自适应学习率项),并将两者结合起来更新参数。

在香蕉函数上进行测试,Adam 的表现优于 RMSprop。在同样 1000 次迭代下,Adam 能够稳定地走到全局最优点,而 RMSprop 则无法做到。

学习率调度:动态调整学习率

除了优化器本身,我们还可以动态地改变基础学习率 $\eta$。这种技术称为学习率调度 (Learning Rate Scheduling)。一种在训练大模型时常见的策略是“先增后减”:

  • Warm-up (预热):在训练初期,逐渐增大学习率。这可以看作是给优化器一个探索地形的机会,让它更好地估计动量和梯度方差。
  • Decay (衰减):在训练后期,逐渐减小学习率。这有助于模型在最优点附近稳定下来,进行精细调整,避免因学习率过大而在最优解两侧震荡。

优化器总结

方法/技巧 改变了哪个步骤? 带来了什么好处?
Optimizer (Adagrad, Adam 等) 步骤三:优化算法 优化 (找到更低的训练损失)

优化器通常对泛化没有直接帮助。有时使用 Adam 虽然降低了训练损失,但验证损失反而可能比普通梯度下降更高,因为在训练集上找到更低的损失不保证在验证集上表现更好。

Dropout:为泛化而生的优化步骤修改

有一个特殊的方法叫 Dropout,它是一种在训练过程中随机丢弃(即暂时忽略)一部分神经元的技术。在验证和测试时,则会使用所有神经元。

这个概念类似于在腿上绑沙袋进行训练,比赛时取下沙袋就能跑得更快。通过在训练时增加难度,强迫网络学习到更鲁棒的特征,而不是依赖于少数几个神经元的协同作用。

方法/技巧 改变了哪个步骤? 带来了什么好处?
Dropout 步骤三:优化算法 泛化 (降低过拟合)

需要注意的是,Dropout 对优化本身没有好处,甚至会使训练损失变得更高。因此,它只适用于已经出现过拟合(即优化已经做得很好,但验证效果不佳)的情况。

初始化与预训练:赢在起跑线上

梯度下降的起始点,即参数的初始化 (Initialization),也会对最终结果产生巨大影响。不同的初始位置可能会导向不同的局部最优解。

即便使用强大的优化器,好的初始化依然至关重要。例如,使用 Kaiming 初始化(一种根据网络层维度来调整随机初始值范围的方法,由何愷明提出)可以显著改善训练效果,让模型收敛到更低的损失。

更进一步,初始化不仅影响能否找到最低点,还影响找到的最低点的“质量”。一个平坦宽阔的“盆地”型最低点通常比一个尖锐狭窄的“峡谷”型最低点具有更好的泛化能力,因为它对训练数据和测试数据之间的微小差异不那么敏感。

在 2025 年,一个通用的、强大的初始化大招是预训练 (Pre-training)。其核心思想是,在针对目标任务(如下游任务,downstream task)进行训练之前,先让模型在一个大规模、通用的任务(如代理任务,pretext task)上进行学习。例如,在教模型分类动物之前,先让它学习预测一张图片被旋转了多少度。通过这个代理任务,模型可以学到通用的视觉特征,这些特征为后续的分类任务提供了一个极佳的起点。

这种方法通常也被称为自监督学习 (Self-supervised Learning)

方法/技巧 改变了哪个步骤? 带来了什么好处?
Initialization / Pre-training 步骤三:优化算法 (选择起点) 优化 + 泛化

预训练的神奇之处在于,它能同时改善优化(提供更好的起点)和泛化(学到更鲁棒、通用的特征)。

步骤二:函数选择范围(网络架构)

我们希望函数(模型)的选择范围不大不小,恰到好处。范围太小,可能不包含最优解;范围太大,则容易过拟合。设计一个好的网络架构,就是利用领域知识 (Domain Knowledge) 来划定一个既小又包含最优解的函数范围。

CNN:为图像处理量身定做的架构

卷积神经网络 (Convolutional Neural Network, CNN) 是一个利用领域知识设计网络架构的经典范例。对于一张 1000x1000 像素的彩色图像,其输入维度高达 300 万。如果使用全连接网络(MLP),第一层若有 1000 个神经元,参数量就将达到惊人的 30 亿。

然而,处理图像真的需要每个神经元都观察整张图片吗?人类的智慧告诉我们并非如此。

  1. 局部性 (Receptive Field):图像中的基本模式(如鸟嘴、眼睛)通常只占很小一部分区域。因此,我们可以让每个神经元只负责观察一个小的感受野 (Receptive Field),而不是整张图片。这极大地减少了参数数量。
  2. 平移不变性 (Parameter Sharing):同一个模式(如鸟嘴)可能出现在图片的不同位置。检测这些模式的神经元,其功能是相同的,因此它们可以共享同一组参数(这组共享的参数被称为滤波器 Filter卷积核 Kernel)。

通过引入感受野和参数共享 (Parameter Sharing),CNN 本质上是全连接网络的一个简化版。它限制了函数的搜索范围,排除了那些我们根据领域知识认为不可能是最优解的函数,从而形成了一个更小、更优的函数集合。

方法/技巧 改变了哪个步骤? 带来了什么好处?
CNN 步骤二:函数范围 泛化 (为图像任务设计,避免过拟合)

Skip Connection 与 Normalization:为优化服务的架构

网络架构的设计不仅影响泛化,也深刻影响优化过程。在深度网络中,一个常见的问题是梯度消失 (Gradient Vanishing)梯度爆炸 (Gradient Explode),即梯度在反向传播过程中变得过小或过大,导致底层网络难以训练。

跳跃连接 (Skip Connection) 或称残差连接 (Residual Connection),通过在网络中创建“高速公路”,让输入信号可以直接跳过多层传递到后面,从而也为梯度提供了一条无障碍的传播路径。这极大地缓解了梯度消失问题,使得损失曲面变得更加平滑,让训练非常深的网络成为可能。

另一类有助于优化的架构设计是归一化 (Normalization),如批量归一化 (Batch Normalization)层归一化 (Layer Normalization)。它们通过对每一层网络的输出进行重新缩放,将其限制在特定范围内(例如均值为0,方差为1)。这有助于稳定训练过程,使得我们可以使用更大的学习率,从而加速优化。

方法/技巧 改变了哪个步骤? 带来了什么好处?
Skip Connection 步骤二:函数范围 优化 (让损失曲面更平滑)
Normalization 步骤二:函数范围 优化 (稳定训练) + 轻微泛化

步骤一:损失函数的定义

分类任务的损失函数:交叉熵

对于回归任务,我们通常使用均方误差(MSE)作为损失函数。但对于分类任务,例如图像分类,我们关心的是准确率 (Accuracy)。然而,准确率是一个不可微的函数(参数的微小变化通常不会改变最终分类结果,导致梯度为零),因此不能直接用作梯度下降的损失函数。

为了解决这个问题,我们使用交叉熵 (Cross-Entropy) 作为分类任务的标准损失函数。它是一种衡量两个概率分布之间差异的指标。我们会先通过 Softmax 函数将网络输出的原始分数(logits)转换为一个概率分布,然后计算这个预测概率分布与表示真实标签的“one-hot”概率分布之间的交叉熵。交叉熵是平滑且可微的,非常适合梯度下降。

| 方法/技巧 | 改变了哪个步骤? | 带来了什么好处? | | :--- | :--- | | Cross-Entropy | 步骤一:损失函数 | 优化 (使分类任务可被梯度下降优化) |

需要注意的是,训练时优化交叉熵,而测试时评估准确率,这本身就引入了训练和评估之间的不匹配,可能对泛化产生细微的负面影响。

数据的力量:更多数据与数据增强

克服过拟合最直接、最有效的方法就是收集更多的训练数据。数据越多,模型就越能学习到具有代表性的真实世界分布。

方法/技巧 改变了哪个步骤? 带来了什么好处?
更多数据 步骤一:损失函数 (改变求和项) 泛化 (最有效的抗过拟合方法)

当无法收集更多真实数据时,我们可以使用数据增强 (Data Augmentation) 来人工创造新数据。例如,对于图像,可以进行翻转、裁剪、模糊、变色等操作;对于语音,可以改变音量、语速或转换声音。一种有趣的技术是 Mixup,它将两张图片及其标签按一定比例混合,生成新的训练样本。

数据增强同样会使优化变得更困难,但能显著提升模型的泛化能力。

半监督学习:利用无标签数据

在很多场景下,无标签数据远比有标签数据更容易获取。半监督学习 (Semi-supervised Learning) 就是利用大量无标签数据来辅助模型训练的方法。这通常基于一些假设:

  1. 聚类假设:相似的数据点应该属于同一类别。
  2. 低密度分离假设:决策边界应该穿过数据密度低的区域。

基于这些假设,我们可以设计额外的损失项来利用无标签数据。例如,可以鼓励模型对无标签数据的预测具有较低的熵(即更自信的预测),或者鼓励相似的无标签数据点拥有相似的预测结果。

方法/技巧 改变了哪个步骤? 带来了什么好处?
Semi-supervised Learning 步骤一:损失函数 泛化

正则化:对参数的偏好

除了基于数据的损失,我们还可以定义一些与数据无关、仅反映我们对参数偏好的损失项,这被称为正则化 (Regularization)。我们通常偏好更“简单”或“平滑”的函数,因为根据奥卡姆剃刀原则,这样的函数泛化能力更强。

在实践中,“简单”通常被定义为参数的数值更小。L2 正则化通过在损失函数中加入一个惩罚项(所有参数的平方和),来鼓励模型学习到更小的权重。

在优化算法的视角下,L2 正则化等价于权重衰减 (Weight Decay),即在每次参数更新时,都先将参数值乘以一个小于 1 的系数(如 0.999),使其“衰减”一点。

AdamW 是一个将权重衰减与 Adam 优化器正确结合的版本。它在 Adam 的基础上加入了权重衰减,从而在保持强大优化能力的同时,提升了泛化性能。

方法/技巧 改变了哪个步骤? 带来了什么好处?
L2 Regularization / Weight Decay 步骤一 (损失) / 步骤三 (优化) 泛化
AdamW 步骤三:优化算法 优化 + 泛化

结语:掌握分析框架

今天我们介绍了大量训练神经网络的技巧。如果你无法记住所有细节,请务必记住这个核心的分析框架:

当你遇到任何一个新方法时,问自己两个问题:

  1. 它改变了机器学习的哪一个步骤?(损失、架构、还是优化?)
  2. 它的主要目的是为了改善优化,还是为了增强泛化?

掌握了这个框架,你就能更深刻地理解各种技术的本质,并在实践中做出更明智的选择。

📌 文中提及的人物和组织

产品/模型: BERT

关键字: design learning model neural-network-training optimization