神经网络训练流程详解

article 约 15 分钟

刚开始学习神经网络时,真正容易让人混乱的往往不是某一个公式,而是这些概念之间的关系:前向传播、激活函数、损失函数、反向传播、优化器、学习率……它们分别解决什么问题,又如何组成一次完整训练?

先记住整篇文章最重要的一句话:

前向传播计算预测,损失函数衡量误差,反向传播计算梯度,优化器更新参数,学习率控制每次更新的尺度。

本文使用同一个二分类网络,从数值计算到公式推导完整走一遍训练流程。为了保持严谨,先约定几个术语:

  • 参数(parameter):模型通过训练学习的量,例如权重和偏置。
  • 超参数(hyperparameter):训练前人为设定的量,例如学习率、批大小和训练轮数。
  • 梯度(gradient):目标函数对参数的偏导数组成的向量,描述目标函数上升最快的方向。
  • 一次迭代(step / iteration):使用一个批次完成一次前向传播、反向传播和参数更新。
  • 一轮训练(epoch):让训练集中的每个样本大致被使用一次。

1. 贯穿全文的例子

考虑一个只有单个样本的二分类任务。输入与标签分别为:

x=[x1x2]=[12],y=1\boldsymbol{x}= \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \qquad y=1

网络包含两个隐藏神经元和一个输出神经元,所有神经元都使用 Sigmoid 激活:

(x₁, x₂) → 两个隐藏神经元 (a₁, a₂) → 输出概率 ŷ

隐藏层参数为:

W=[w11w12w21w22]=[0.10.20.10.1],b=[b1b2]=[00.1]\boldsymbol{W}= \begin{bmatrix} w_{11} & w_{12} \\ w_{21} & w_{22} \end{bmatrix} = \begin{bmatrix} 0.1 & 0.2 \\ -0.1 & 0.1 \end{bmatrix}, \qquad \boldsymbol{b}= \begin{bmatrix} b_1 \\ b_2 \end{bmatrix} = \begin{bmatrix} 0 \\ 0.1 \end{bmatrix}

这里采用“矩阵的第 jj 行对应第 jj 个隐藏神经元”的约定。例如,w12w_{12} 表示输入 x2x_2 到第 11 个隐藏神经元的权重。

输出层参数为:

v=[v1v2]=[0.30.4],b3=0.1\boldsymbol{v}= \begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = \begin{bmatrix} 0.3 \\ -0.4 \end{bmatrix}, \qquad b_3=0.1

本文中的数值均保留四位小数,因此中间步骤可能存在轻微的舍入误差。

2. 神经网络究竟在学习什么?

神经网络本质上是一个带参数的函数。以最简单的线性模型为例:

y=wx+by=wx+b

其中 xx 是输入,yy 是输出,wwbb 是需要学习的参数。神经网络只是把更多线性变换与非线性激活组合起来:

fθ(x)=fL ⁣(fL1 ⁣(f1(x)))f_{\boldsymbol{\theta}}(\boldsymbol{x}) =f_L\!\left(f_{L-1}\!\left(\cdots f_1(\boldsymbol{x})\right)\right)

θ\boldsymbol{\theta} 表示网络中的全部参数。训练的目标不是“记住数据”,而是找到一组参数,使模型在未见数据上也能较好地近似输入到目标的映射。

一次训练迭代由以下步骤组成:

取出一个批次的数据
  → 前向传播,得到预测
  → 计算目标函数
  → 反向传播,得到梯度
  → 优化器更新参数
  → 进入下一次迭代

这条闭环会重复很多次,直到验证集指标不再改善、达到预定训练轮数,或触发其他停止条件。

3. 前向传播:由输入得到预测

前向传播使用当前参数从输入逐层计算模型输出。对本文的网络,隐藏层可以整体写成:

z=Wx+b,a=σ(z)\boldsymbol{z}=\boldsymbol{W}\boldsymbol{x}+\boldsymbol{b}, \qquad \boldsymbol{a}=\sigma(\boldsymbol{z})

其中 σ()\sigma(\cdot) 按元素作用。展开第 11 个隐藏神经元:

z1=w11x1+w12x2+b1=0.1×1+0.2×2+0=0.5,a1=σ(z1)=σ(0.5)0.6225\begin{aligned} z_1 &=w_{11}x_1+w_{12}x_2+b_1 \\ &=0.1\times1+0.2\times2+0 \\ &=0.5, \\ a_1 &=\sigma(z_1) \\ &=\sigma(0.5) \\ &\approx0.6225 \end{aligned}

22 个隐藏神经元为:

z2=w21x1+w22x2+b2=(0.1)×1+0.1×2+0.1=0.2,a2=σ(z2)=σ(0.2)0.5498\begin{aligned} z_2 &=w_{21}x_1+w_{22}x_2+b_2 \\ &=(-0.1)\times1+0.1\times2+0.1 \\ &=0.2, \\ a_2 &=\sigma(z_2) \\ &=\sigma(0.2) \\ &\approx0.5498 \end{aligned}

输出层先计算 logit z3z_3,再将它映射为正类概率 y^\hat{y}

z3=v1a1+v2a2+b3=0.3×0.62250.4×0.5498+0.10.0668,y^=σ(z3)0.5167\begin{aligned} z_3 &=v_1a_1+v_2a_2+b_3 \\ &=0.3\times0.6225-0.4\times0.5498+0.1 \\ &\approx0.0668, \\ \hat{y} &=\sigma(z_3) \\ &\approx0.5167 \end{aligned}

因此,模型当前认为该样本属于正类的概率约为 51.67%51.67\%。真实标签为 y=1y=1,预测方向虽然正确,但置信度很低。

4. 激活函数:为网络引入非线性

若各层都只进行线性变换,那么无论叠加多少层,整体仍然等价于一次线性变换:

W2(W1x+b1)+b2=Wx+b\boldsymbol{W}_2(\boldsymbol{W}_1\boldsymbol{x}+\boldsymbol{b}_1)+\boldsymbol{b}_2 =\boldsymbol{W}'\boldsymbol{x}+\boldsymbol{b}'

激活函数使网络能够表达非线性关系。下面是几种常见选择。

4.1 Sigmoid

σ(z)=11+ez,σ(z)=σ(z)(1σ(z))\sigma(z)=\frac{1}{1+e^{-z}}, \qquad \sigma'(z)=\sigma(z)\bigl(1-\sigma(z)\bigr)

Sigmoid 的值域是 (0,1)(0,1),因此常用于二分类输出层。它在输入绝对值较大时会进入饱和区,导数接近 00,所以通常不再作为深层前馈网络隐藏层的默认选择。

4.2 Tanh

tanh(z)=ezezez+ez,tanh(z)=1tanh2(z)\tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}}, \qquad \tanh'(z)=1-\tanh^2(z)

Tanh 的值域是 (1,1)(-1,1),输出以 00 为中心,但同样存在饱和区和梯度消失问题。它仍常见于部分循环结构和需要有界输出的场景。

4.3 ReLU 与 Leaky ReLU

ReLU(z)=max(0,z)\operatorname{ReLU}(z)=\max(0,z) ReLU(z)={1,z>0,0,z<0\operatorname{ReLU}'(z)= \begin{cases} 1, & z>0, \\ 0, & z<0 \end{cases}

ReLU 计算简单、正半轴不饱和,是许多网络隐藏层的常见默认选择。在 z=0z=0 处它不可导,实际实现会指定一个次梯度;负半轴梯度始终为 00,可能导致“死亡 ReLU”。

Leaky ReLU 在负半轴保留一个很小的斜率:

LeakyReLU(z)={z,z>0,αz,z0,α>0\operatorname{LeakyReLU}(z)= \begin{cases} z, & z>0, \\ \alpha z, & z\le 0 \end{cases}, \qquad \alpha>0

它可以缓解神经元长期没有梯度的问题,但 α\alpha 仍需设定。

4.4 Softmax

对于 KK 个互斥类别,Softmax 将 logits z1,z2,,zKz_1,z_2,\ldots,z_K 转换为概率分布:

softmax(z)i=ezij=1Kezj,i=1,2,,K\operatorname{softmax}(\boldsymbol{z})_i =\frac{e^{z_i}}{\sum_{j=1}^{K}e^{z_j}}, \qquad i=1,2,\ldots,K

各项均为正数且总和为 11。工程实现通常会先减去 maxizi\max_i z_i,以避免指数运算溢出;这一操作不会改变 Softmax 的结果。

激活函数常见位置主要特点主要风险
Sigmoid二分类输出层输出可解释为正类概率饱和区梯度很小
Tanh部分循环结构零中心、有界仍可能梯度消失
ReLU隐藏层简单、高效、正半轴不饱和死亡 ReLU
Leaky ReLU隐藏层负半轴保留梯度需选择负半轴斜率
Softmax单标签多分类输出层输出类别概率分布需注意数值稳定性

二分类通常使用 Sigmoid;单标签多分类通常使用 Softmax;多标签分类则常对每个标签独立使用 Sigmoid。

5. 损失函数与目标函数

前向传播产生预测后,需要用损失函数衡量预测与真实目标之间的差异。

5.1 均方误差

均方误差(Mean Squared Error, MSE)常用于回归任务。对包含 NN 个样本的数据集:

MSE=1Ni=1N(yiy^i)2\operatorname{MSE} =\frac{1}{N}\sum_{i=1}^{N}\left(y_i-\hat{y}_i\right)^2

平方会使较大的误差受到更重的惩罚。MSE 可导且形式简单,但对离群值较敏感。

5.2 二元交叉熵

本文是二分类问题,使用二元交叉熵(Binary Cross-Entropy, BCE):

(y,y^)=[ylny^+(1y)ln(1y^)]\ell(y,\hat{y}) =-\left[y\ln\hat{y}+(1-y)\ln(1-\hat{y})\right]

其中 y{0,1}y\in\{0,1\}y^(0,1)\hat{y}\in(0,1)。当 y=1y=1 时,损失化简为:

(1,y^)=lny^\ell(1,\hat{y})=-\ln\hat{y}

代入本文的预测 y^0.5167\hat{y}\approx0.5167

L=ln(0.5167)0.6603L=-\ln(0.5167)\approx0.6603

模型给真实类别的概率越小,交叉熵惩罚越大。在实际代码中,通常应使用直接接收 logits 的稳定实现,例如 PyTorch 的 BCEWithLogitsLoss,而不是先手动计算 Sigmoid 再取对数。

5.3 多分类交叉熵

CC 个互斥类别,多分类交叉熵为:

(y,y^)=c=1Cyclny^c\ell(\boldsymbol{y},\hat{\boldsymbol{y}}) =-\sum_{c=1}^{C}y_c\ln\hat{y}_c

y\boldsymbol{y} 是 one-hot 向量,只有真实类别 kk 对应的 yk=1y_k=1,因此:

=lny^k\ell=-\ln\hat{y}_k

5.4 从样本损失到训练目标

“损失函数”和“目标函数”经常被混用,但严格来说它们处于不同层次:

  • 样本损失 i\ell_i:衡量单个样本的预测误差。
  • 经验风险 L(θ)L(\boldsymbol{\theta}):一个批次或整个训练集上的平均损失。
  • 目标函数 J(θ)J(\boldsymbol{\theta}):优化器真正最小化的量,可额外包含正则化项。

例如,带 L2L_2 正则化的目标函数可以写成:

J(θ)=1Ni=1Ni(θ)+λ2W22J(\boldsymbol{\theta}) =\frac{1}{N}\sum_{i=1}^{N}\ell_i(\boldsymbol{\theta}) +\frac{\lambda}{2}\lVert\boldsymbol{W}\rVert_2^2

λ0\lambda\ge0 控制正则化强度。正则化会限制参数过度增大,从而降低过拟合风险,但它不能代替独立验证集上的泛化评估。

6. 反向传播:用链式法则计算梯度

反向传播(backpropagation)是一种高效计算梯度的算法。它计算梯度,但不更新参数;参数更新由优化器完成。

6.1 链式法则

u=g(x)u=g(x)z=f(u)z=f(u),则:

dzdx=dzdududx\frac{\mathrm{d}z}{\mathrm{d}x} =\frac{\mathrm{d}z}{\mathrm{d}u} \frac{\mathrm{d}u}{\mathrm{d}x}

神经网络是嵌套的复合函数。例如,参数 w11w_{11} 影响损失 LL 的路径为:

w₁₁ → z₁ → a₁ → z₃ → ŷ → L

因此:

Lw11=Ly^y^z3z3a1a1z1z1w11\frac{\partial L}{\partial w_{11}} =\frac{\partial L}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial z_3} \frac{\partial z_3}{\partial a_1} \frac{\partial a_1}{\partial z_1} \frac{\partial z_1}{\partial w_{11}}

反向传播会复用中间结果,而不是为每个参数单独重算整条路径,这正是它高效的原因。

6.2 输出层梯度

当 Sigmoid 与二元交叉熵组合时,损失对输出层 logit 的导数可以化简为:

Lz3=y^y\frac{\partial L}{\partial z_3}=\hat{y}-y

代入 y^0.5167\hat{y}\approx0.5167y=1y=1

δ3Lz3=0.51671=0.4833\delta_3 \coloneqq\frac{\partial L}{\partial z_3} =0.5167-1 =-0.4833

因为:

z3=v1a1+v2a2+b3z_3=v_1a_1+v_2a_2+b_3

所以输出层参数的梯度为:

Lv1=δ3a10.4833×0.62250.3008,Lv2=δ3a20.4833×0.54980.2657,Lb3=δ30.4833\begin{aligned} \frac{\partial L}{\partial v_1} &=\delta_3a_1 \approx-0.4833\times0.6225 \approx-0.3008, \\ \frac{\partial L}{\partial v_2} &=\delta_3a_2 \approx-0.4833\times0.5498 \approx-0.2657, \\ \frac{\partial L}{\partial b_3} &=\delta_3 \approx-0.4833 \end{aligned}

6.3 隐藏层梯度

对第 jj 个隐藏神经元,误差信号为:

δjLzj=δ3vjaj(1aj)\delta_j \coloneqq\frac{\partial L}{\partial z_j} =\delta_3v_j\,a_j(1-a_j)

11 个隐藏神经元:

δ1=(0.4833)×0.3×0.6225×(10.6225)0.0341\begin{aligned} \delta_1 &=(-0.4833)\times0.3\times0.6225\times(1-0.6225) \\ &\approx-0.0341 \end{aligned}

z1=w11x1+w12x2+b1z_1=w_{11}x_1+w_{12}x_2+b_1 可得:

Lw11=δ1x10.0341,Lw12=δ1x20.0681,Lb1=δ10.0341\begin{aligned} \frac{\partial L}{\partial w_{11}} &=\delta_1x_1\approx-0.0341, \\ \frac{\partial L}{\partial w_{12}} &=\delta_1x_2\approx-0.0681, \\ \frac{\partial L}{\partial b_1} &=\delta_1\approx-0.0341 \end{aligned}

22 个隐藏神经元:

δ2=(0.4833)×(0.4)×0.5498×(10.5498)0.0479\begin{aligned} \delta_2 &=(-0.4833)\times(-0.4)\times0.5498\times(1-0.5498) \\ &\approx0.0479 \end{aligned}

从而:

Lw21=δ2x10.0479,Lw22=δ2x20.0957,Lb2=δ20.0479\begin{aligned} \frac{\partial L}{\partial w_{21}} &=\delta_2x_1\approx0.0479, \\ \frac{\partial L}{\partial w_{22}} &=\delta_2x_2\approx0.0957, \\ \frac{\partial L}{\partial b_2} &=\delta_2\approx0.0479 \end{aligned}

梯度汇总如下:

参数梯度参数梯度
w11w_{11}0.0341-0.0341w12w_{12}0.0681-0.0681
w21w_{21}0.04790.0479w22w_{22}0.09570.0957
b1b_10.0341-0.0341b2b_20.04790.0479
v1v_10.3008-0.3008v2v_20.2657-0.2657
b3b_30.4833-0.4833

梯度的正负不表示参数“好”或“坏”。它只描述在当前位置轻微增大该参数时,损失的一阶变化方向。

7. 梯度下降:根据梯度更新参数

最基本的梯度下降更新规则为:

θθηJθ\theta\leftarrow\theta-\eta\frac{\partial J}{\partial\theta}

其中 η>0\eta>0 是学习率。梯度指向目标函数上升最快的方向,因此要沿其反方向更新。

η=0.1\eta=0.1,以 v1v_1 为例:

v1new=v1oldηLv1=0.30.1×(0.3008)0.3301\begin{aligned} v_1^{\text{new}} &=v_1^{\text{old}}-\eta\frac{\partial L}{\partial v_1} \\ &=0.3-0.1\times(-0.3008) \\ &\approx0.3301 \end{aligned}

全部参数更新后为:

参数更新前梯度更新后
w11w_{11}0.10000.10000.0341-0.03410.10340.1034
w12w_{12}0.20000.20000.0681-0.06810.20680.2068
b1b_10.00000.00000.0341-0.03410.00340.0034
w21w_{21}0.1000-0.10000.04790.04790.1048-0.1048
w22w_{22}0.10000.10000.09570.09570.09040.0904
b2b_20.10000.10000.04790.04790.09520.0952
v1v_10.30000.30000.3008-0.30080.33010.3301
v2v_20.4000-0.40000.2657-0.26570.3734-0.3734
b3b_30.10000.10000.4833-0.48330.14830.1483

使用这些新参数再次前向传播,会得到更大的正类概率和更小的损失。这只是沿局部负梯度方向走一步的结果,并不保证任意学习率下每一步都使损失下降。

8. Batch GD、SGD 与 Mini-batch GD

三者的核心差异,是一次参数更新使用多少训练样本来估计梯度

方法每次更新使用的数据优点局限
Batch Gradient Descent整个训练集梯度稳定单次更新成本高,内存压力大
Stochastic Gradient Descent单个样本更新频繁,单步成本低梯度噪声大,硬件利用率低
Mini-batch Gradient Descent一个小批次兼顾效率、稳定性和并行计算需要选择批大小

现代深度学习训练通常使用 mini-batch。实践中,人们也经常把“使用 mini-batch 的普通随机梯度下降优化器”简称为 SGD,需要结合上下文判断其含义。

若批次 B\mathcal{B} 包含 BB 个样本,批次平均损失为:

LB(θ)=1BiBi(θ)L_{\mathcal{B}}(\boldsymbol{\theta}) =\frac{1}{B}\sum_{i\in\mathcal{B}}\ell_i(\boldsymbol{\theta})

反向传播计算的是 θLB\nabla_{\boldsymbol{\theta}}L_{\mathcal{B}},它是整个训练集梯度的带噪估计。

9. Adam:自适应地缩放每个参数的更新

Adam(Adaptive Moment Estimation)仍然依赖反向传播得到的梯度。它与普通 SGD 的区别在于:Adam 会维护梯度的一阶矩和二阶原点矩的指数移动平均,为不同参数自适应地缩放更新量。

令第 tt 步梯度为:

gt=θJt(θt1)g_t=\nabla_{\theta}J_t(\theta_{t-1})

一阶矩估计为:

mt=β1mt1+(1β1)gtm_t=\beta_1m_{t-1}+(1-\beta_1)g_t

二阶原点矩估计为:

st=β2st1+(1β2)gt2s_t=\beta_2s_{t-1}+(1-\beta_2)g_t^2

其中平方按元素计算。由于 m0=s0=0m_0=s_0=0,训练初期的估计会偏向 00,因此需要做偏差修正:

m^t=mt1β1t,s^t=st1β2t\hat{m}_t=\frac{m_t}{1-\beta_1^t}, \qquad \hat{s}_t=\frac{s_t}{1-\beta_2^t}

最终更新规则为:

θt=θt1ηm^ts^t+ε\theta_t =\theta_{t-1} -\eta\frac{\hat{m}_t}{\sqrt{\hat{s}_t}+\varepsilon}

常见默认值是 β1=0.9\beta_1=0.9β2=0.999\beta_2=0.999ε=108\varepsilon=10^{-8},但它们并非适用于所有任务的定律。

9.1 用 v1v_1 演示第一次 Adam 更新

已知 g1=L/v10.3008g_1=\partial L/\partial v_1\approx-0.3008,并令 m0=s0=0m_0=s_0=0

m1=0.9×0+0.1×(0.3008)=0.03008,s1=0.999×0+0.001×(0.3008)20.00009048\begin{aligned} m_1 &=0.9\times0+0.1\times(-0.3008) =-0.03008, \\ s_1 &=0.999\times0+0.001\times(-0.3008)^2 \approx0.00009048 \end{aligned}

偏差修正后:

m^1=0.0300810.9=0.3008,s^1=0.0000904810.9990.09048\hat{m}_1 =\frac{-0.03008}{1-0.9} =-0.3008, \qquad \hat{s}_1 =\frac{0.00009048}{1-0.999} \approx0.09048

η=0.001\eta=0.001,则:

v1new=0.30.0010.30080.09048+1080.3010\begin{aligned} v_1^{\text{new}} &=0.3-0.001\frac{-0.3008}{\sqrt{0.09048}+10^{-8}} \\ &\approx0.3010 \end{aligned}

第一次更新时,偏差修正使 m^1=g1\hat{m}_1=g_1s^1=g12\hat{s}_1=g_1^2,因此除极小的 ε\varepsilon 外,更新幅度接近学习率、方向由梯度符号决定。Adam 的自适应优势主要体现在累积了多步梯度历史之后。

9.2 常见优化器对比

优化器核心机制常见特点
SGD直接使用当前批次梯度简单、内存占用低,对学习率敏感
SGD + Momentum累积梯度方向减少震荡,加速沿一致方向前进
RMSProp使用梯度平方的移动平均为各参数自适应缩放步长
Adam同时使用一阶矩与二阶原点矩通常收敛快,对初始学习率相对宽容
AdamW将权重衰减与梯度更新解耦Transformer 等模型中的常见选择

Adam 并不保证在所有任务上都优于 SGD。选择优化器时,应同时比较收敛速度、验证集指标、训练稳定性和计算资源。

10. 学习率:决定更新尺度

对普通梯度下降:

Δθ=ηJθ\Delta\theta=-\eta\frac{\partial J}{\partial\theta}

学习率 η\eta 是控制参数更新尺度的超参数:

  • 过大:损失可能震荡、发散,甚至出现 NaN
  • 过小:训练进展缓慢,也可能在有限预算内无法到达较好区域。

下表给出常见现象与排查方向,但同一现象可能有多个原因,不能只凭一条曲线直接下结论。

训练现象可能原因优先排查
损失迅速发散或出现 NaN学习率过大、数值溢出、数据异常降低学习率,检查输入与稳定损失实现
训练损失大幅震荡学习率偏大、批次过小降低学习率或增大批次
训练损失下降很慢学习率偏小、梯度过小、模型容量不足检查梯度与数据,再调整学习率
训练损失下降而验证损失上升过拟合或数据分布差异正则化、数据增强、早停、检查划分
后期长期停滞学习率不合适或已接近当前配置上限尝试衰减学习率,并检查模型与数据

所谓“推荐初始学习率”只能作为搜索起点。它还会受到优化器、批大小、归一化方式、模型规模和任务类型的共同影响。

11. 学习率调度:让不同阶段使用不同步长

训练早期通常需要较大的步长快速移动,训练后期则需要较小的步长精细调整。学习率调度器用于随训练进程改变全局学习率。

11.1 Step Decay

每隔固定步数将学习率乘以衰减系数 γ\gamma

ηt=η0γt/Tstep,0<γ<1\eta_t =\eta_0\gamma^{\left\lfloor t/T_{\text{step}}\right\rfloor}, \qquad 0<\gamma<1

它简单直观,但衰减时点和幅度需要预先指定。

11.2 Exponential Decay

ηt=η0γt,0<γ<1\eta_t=\eta_0\gamma^t, \qquad 0<\gamma<1

学习率连续、平滑地下降。若 γ\gamma 过小,学习率可能过早衰减到几乎无法更新。

11.3 Cosine Annealing

ηt=ηmin+12(ηmaxηmin)(1+cosπtT),0tT\eta_t =\eta_{\min} +\frac{1}{2}(\eta_{\max}-\eta_{\min}) \left(1+\cos\frac{\pi t}{T}\right), \qquad 0\le t\le T

它将学习率从 ηmax\eta_{\max} 平滑降到 ηmin\eta_{\min},是现代深度学习中的常见选择。

11.4 Warmup

线性 warmup 在训练初期逐步提高学习率:

ηt=ηtargettTwarmup,0tTwarmup\eta_t =\eta_{\text{target}}\frac{t}{T_{\text{warmup}}}, \qquad 0\le t\le T_{\text{warmup}}

Warmup 常用于 Transformer、大批量训练或初期梯度不稳定的任务。它通常与后续衰减策略组合使用,而不是独立覆盖整个训练过程。

11.5 ReduceLROnPlateau

当验证集指标连续若干轮没有改善时,将学习率乘以一个小于 11 的因子。它根据指标自适应调整,但效果依赖监控指标、耐心值(patience)、阈值和衰减因子的合理设置。

11.6 One Cycle

One Cycle 通常让学习率先从较小值升至峰值,再下降到远低于初始值的水平,并常与动量的反向变化配合。它可能加快训练并改善泛化,但需要合理估计最大学习率。

调度方法学习率变化适合场景
Step Decay阶梯式下降训练周期固定、基线实验
Exponential Decay指数下降希望持续平滑衰减
Cosine Annealing余弦下降深度网络常规训练
Warmup初期逐渐升高Transformer、大批量训练
ReduceLROnPlateau指标停滞后下降难以预判衰减时点
One Cycle先升后降希望提高训练效率的成熟配置

学习率调度与 Adam 并不冲突。调度器控制全局基准学习率 ηt\eta_t,Adam 再依据每个参数的梯度历史进行缩放:

实际更新=全局学习率×逐参数自适应缩放\text{实际更新} =\text{全局学习率} \times\text{逐参数自适应缩放}

12. 把训练闭环写成伪代码

下面的伪代码对应绝大多数监督学习训练程序:

for epoch in range(num_epochs):
    model.train()

    for x_batch, y_batch in train_loader:
        optimizer.zero_grad()       # 清除上一次迭代留下的梯度
        logits = model(x_batch)     # 前向传播
        loss = criterion(logits, y_batch)
        loss.backward()             # 反向传播,计算梯度
        optimizer.step()            # 根据梯度更新参数

    validate(model, val_loader)     # 在验证集上评估泛化表现
    scheduler.step()                # 调度时点取决于调度器类型

需要注意:

  • model.train() 不是“执行训练”,而是让 Dropout、Batch Normalization 等模块进入训练模式。
  • loss.backward() 只计算并累积梯度;optimizer.step() 才更新参数。
  • 某些调度器按迭代调用,某些按 epoch 调用;ReduceLROnPlateau 还需要传入验证指标。
  • 验证阶段不应更新参数,并应关闭不必要的梯度记录。

13. 常见概念辨析

易混概念准确关系
前向传播 vs. 推理两者都会计算输出;训练中的前向传播还会为求梯度保留必要的中间量
反向传播 vs. 梯度下降反向传播计算梯度;梯度下降使用梯度更新参数
损失函数 vs. 目标函数损失描述预测误差;目标函数是最终被最小化的完整表达式
参数 vs. 超参数参数由训练学习;超参数由训练者设定或搜索
Adam vs. 学习率调度Adam 逐参数缩放更新;调度器改变全局基准学习率
epoch vs. iterationepoch 是大致遍历一次训练集;iteration 是完成一次参数更新

最后,将全文压缩成一个闭环:

数据 → 前向传播 → 预测 → 损失/目标函数
     → 反向传播 → 梯度 → 优化器更新参数
     → 学习率调度 → 下一次迭代

理解神经网络训练的关键,不是孤立地记住每个名词,而是明确每个环节的输入和输出:前向传播输出预测,损失函数输出标量误差,反向传播输出梯度,优化器输出更新后的参数。只要这条数据流清晰,复杂网络的训练逻辑仍然是同一个闭环。

评论