Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

梯度下降

前两章,我们构建了模型的基本框架:

  • 前向传播:根据模型参数(权重和偏置)计算预测值;

  • 损失函数:量化预测值与真实的标签之间的误差。

目前的模型参数是我们手动初始化的,从推理评估的结果看,并不准确。现在我们面临的核心问题是:如何调整模型参数,让损失值变小?

答案是:让网络模型从数据中自动学习,这个过程称为模型训练(Model Training)。

模型训练

模型训练的目标很明确:找到一组模型参数(权重和偏置),使损失值尽可能小。

这是一个经典的数学问题:函数最优化(Function Optimization)。一个同样经典的比喻是:如果把损失值看作一座山,模型训练的目标就是找到山谷(损失值最小的地方)。

神经网络使用的优化方法叫梯度下降法(Gradient Descent)。它的思路非常直观:站在山上,每次都朝着最陡的下坡方向迈一步,最终就能走到山谷。


具体来说,如果我们把推理函数代入损失函数,就会发现损失值 LL 是权重 ww 和偏置 bb 的函数,记作 L(w,b)L(w, b)。

梯度(Gradient)就是这个函数“上坡最陡”的方向,用数学语言表达就是偏导数:

∇L=(∂L∂w, ∂L∂b)\nabla L = \left( \frac{\partial L}{\partial w},\ \frac{\partial L}{\partial b} \right)

下降(Descent)就是让参数沿梯度相反的方向移动一步。因为梯度指向上坡,反方向自然就是下坡:

wnew=wold−∂L∂ww_{\text{new}} = w_{\text{old}} - \frac{\partial L}{\partial w}
bnew=bold−∂L∂bb_{\text{new}} = b_{\text{old}} - \frac{\partial L}{\partial b}

梯度计算

梯度是损失函数对模型参数的偏导数。计算梯度有三种方式:

数值微分(Numerical Differentiation)

给每个参数加一个微小扰动 ϵ\epsilon,观察损失的变化来(近似)计算导数:

∂L∂wi≈L(wi+ϵ)−L(wi)ϵ\frac{\partial L}{\partial w_i} \approx \frac{L(w_i + \epsilon) - L(w_i)}{\epsilon}

在模型训练中这样做代价极高:有多少个参数,就需要做多少次前向传播。一个百万参数的模型需要运行一百万次推理,完全不可接受。

符号微分(Symbolic Differentiation)

手动推导每个参数的导数公式。对简单的线性回归还好,但实际应用的网络模型可能有几十层、包含各种非线性变换,手推公式可能长达数页,导致表达式爆炸。更致命的是,每次修改网络结构,所有公式就要推倒重来。

自动微分(Automatic Differentiation)

利用微积分的链式法则(Chain Rule)。它的核心思想是:任何复杂的运算都可以拆解为简单的基本运算的组合,而每种基本运算的导数规则是固定已知的。将前向传播的计算分解为基本计算的组合,就能反向应用链式法则,逐步计算出所有参数的梯度。

损失值 LL 是预测值 pp 的函数(损失函数),预测值 pp 又是模型参数 ww、bb 的函数(推理函数)。根据微积分的链式法则,可以把它们的导数“链”起来,得到损失值关于参数的导数:

∂L∂w=∂L∂p⋅∂p∂w,∂L∂b=∂L∂p⋅∂p∂b\frac{\partial L}{\partial w} = \frac{\partial L}{\partial p} \cdot \frac{\partial p}{\partial w}, \qquad \frac{\partial L}{\partial b} = \frac{\partial L}{\partial p} \cdot \frac{\partial p}{\partial b}

现在,让我们利用链式法则推导一下梯度的计算公式。

第一步:计算损失函数关于预测值的导数。损失函数(单样本):L=(y−p)2L = (y - p)^2,对 pp 求导:

∂L∂p=−2(y−p)\frac{\partial L}{\partial p} = -2(y - p)

第二步:计算推理函数关于参数的导数。推理函数:p=w⋅x+bp = w \cdot x + b,分别对 ww 和 bb 求导:

∂p∂w=x,∂p∂b=1\frac{\partial p}{\partial w} = x, \qquad \frac{\partial p}{\partial b} = 1

第三步:用链式法则合并,得到损失值 LL 关于 ww 和 bb 的完整梯度:

∂L∂w=∂L∂p⋅∂p∂w=−2(y−p)⋅x\frac{\partial L}{\partial w} = \frac{\partial L}{\partial p} \cdot \frac{\partial p}{\partial w} = -2(y - p) \cdot x
∂L∂b=∂L∂p⋅∂p∂b=−2(y−p)\frac{\partial L}{\partial b} = \frac{\partial L}{\partial p} \cdot \frac{\partial p}{\partial b} = -2(y - p)

这两个梯度公式的公共部分,也就是损失函数关于预测值的导数:−2(y−p)-2(y - p),在深度学习中有个专门的名字:误差项(Delta),记作 δ\delta:

δ=−2(y−p)\delta = -2(y - p)

有了误差项,梯度可以简洁地表示为:

∂L∂w=δ⋅x,∂L∂b=δ\frac{\partial L}{\partial w} = \delta \cdot x, \qquad \frac{\partial L}{\partial b} = \delta

误差项 δ\delta 的意义非常直观:δ<0\delta < 0,说明模型预测偏低;δ>0\delta > 0,说明模型预测偏高。梯度下降正是利用这个信号来纠正参数的。

数据

模型

梯度下降法分为两个步骤:梯度计算(Gradient Computation)和参数调整(Parameter Update)。我们首先把根据误差项调整模型参数的部分添加到网络模型里,而梯度计算的部分将在损失函数里完成。

反向函数

反向函数利用(损失函数计算的)误差项 δ\delta 更新模型参数:

w←w−δ⋅xw \leftarrow w - \delta \cdot x
b←b−δb \leftarrow b - \delta

这种数据从输出向输入方向流动的过程,称为反向传播(Backpropagation)。

损失函数(均方误差)

误差项 δ\delta 的计算在损失函数内完成。

梯度函数

根据上面的推导,梯度函数根据标签 yy 和预测值 pp 来计算误差项 δ\delta:

δ=−2(y−p)\delta = -2(y - p)

误差项将在模型的反向函数里用于计算权重梯度 δ⋅x\delta \cdot x 和偏置梯度 δ\delta。

建模

训练

现在,我们用梯度下降法进行第一次模型训练。训练过程包括:

  • 前向传播:利用特征和模型参数推理预测值;

  • 计算误差:根据预测值和标签计算误差项;

  • 反向传播:利用误差项计算梯度,进而调整模型参数。

推理

完成训练后,我们用调整后的模型参数再进行一次推理。

prediction:	[1013352.429]

评估

loss:	1026548766283.6302

损失值从 14,872 爆炸到 1,026,548,766,283,增大了近七千万倍。

发生了什么?

预测值从 43 一步跳到了 1,013,352,完全越过了真实值 165,一路冲到了山谷的另一边。这就好比下山时,一脚步子太大,直接踩到了对面的山坡上,甚至比出发点更高。

这种现象在深度学习中称为发散(Divergence):损失值不仅没有降低,反而急剧增大,模型训练失败。

💡 提示:后续章节中,我们将引入学习率(Learning Rate)的概念,来控制模型参数调整的幅度,解决训练过程中梯度发散的问题。

课后练习

  1. 如果预测值比真实值大(预测偏高),误差项 δ\delta 会是正数还是负数?参数会朝哪个方向更新?结合公式思考一下。