AI

d2l:梯度

·10 分钟阅读·3885 字

从偏导数、梯度下降与链式法则出发,理解深度学习中的梯度计算和参数更新

📋 目录

d2l:梯度

能够代表深度学习训练核心的概念之一是梯度(Gradient)。

D2L 学习过程中会涉及很多概念,例如线性回归、Softmax 回归、交叉熵、反向传播、SGD、自动求导等。表面上看,这些内容似乎彼此独立,但实际上,它们全部都围绕着梯度展开。

甚至可以说,深度学习的整个训练过程,本质上就是一个不断计算梯度、利用梯度、更新梯度、传播梯度的过程。

因此,如果不能从数学和工程两个角度真正理解梯度,那么后面的 CNN、Transformer、注意力机制、大模型训练都会变得非常模糊。

本文不局限于某段代码,而是从整个深度学习系统的角度,完整地梳理梯度。


1. 梯度最初来自哪里?

梯度最初来自微积分。

假设有一个函数:

f(x)=x2f(x)=x^2

它的图像是一条抛物线。

如果需要判断:

当 xx 发生微小变化时,函数值 f(x)f(x) 会如何变化?

就需要计算导数:

f′(x)=2xf'(x)=2x

例如:

当:

x=3x=3

那么:

f′(3)=6f'(3)=6

这意味着,当 xx 增加一个极小量时,f(x)f(x) 大约会增加 6 倍的变化量。

导数描述的是:

函数在某一点的瞬时变化率。


但是,深度学习中的参数并不只有一个。

例如,线性回归:

y=w1x1+w2x2+by=w_1x_1+w_2x_2+b

这里有三个参数:

(w1,w2,b)(w_1,w_2,b)

此时,损失函数变成:

L(w1,w2,b)L(w_1,w_2,b)

它是一个三元函数。

于是,普通导数就不够用了。


2. 偏导数:研究单个参数的影响

对于多变量函数:

L(w1,w2,b)L(w_1,w_2,b)

可以分别研究每个参数。

固定其他参数,只改变:

w1w_1

得到:

∂L∂w1\frac{\partial L}{\partial w_1}

同样:

∂L∂w2\frac{\partial L}{\partial w_2}

以及:

∂L∂b\frac{\partial L}{\partial b}

分别表示:

  • w1w_1 对损失的影响
  • w2w_2 对损失的影响
  • bb 对损失的影响

这就是偏导数。与基础微积分中常见的“对输入 xx 求导”不同,模型训练时输入数据 xx 通常已经确定,参数 ww 才是需要优化的变量。为了寻找一组使预测结果接近真实标签的参数,需要计算损失函数对参数 ww 的偏导数。


3. 梯度:所有偏导数组成的向量

把所有偏导数放到一起:

∇L=(∂L∂w1,∂L∂w2,∂L∂b)\nabla L= \left( \frac{\partial L}{\partial w_1}, \frac{\partial L}{\partial w_2}, \frac{\partial L}{\partial b} \right)

这就是梯度。

注意:

梯度不是一个数。

梯度是一个向量。


例如:

假设:

∇L=(5,−2,1)\nabla L=(5,-2,1)

意味着:

  • w1w_1 增大时,损失快速增加
  • w2w_2 增大时,损失反而减小
  • bb 增大时,损失缓慢增加

4. 梯度为什么能够指导训练?

假设损失函数是一个山谷:

      山顶
        ▲
       / \
      /   \
     /     \
    /       \
   ●---------→
      山谷

当前位置:

●

梯度指向哪个方向?

答案是:

梯度永远指向函数增长最快的方向。


例如:

当前位置的梯度:

∇L=(5,3)\nabla L=(5,3)

表示:

向右移动,损失增加。

向上移动,损失增加。


如果想让损失下降,怎么办?

只需要沿着梯度的反方向移动:

−∇L-\nabla L

这就是梯度下降。


5. 梯度下降公式是怎么来的?

更新公式:

θt+1=θt−η∇L(θt)\theta_{t+1} = \theta_t - \eta\nabla L(\theta_t)

其中:

  • θ\theta 是参数
  • η\eta 是学习率
  • ∇L\nabla L 是梯度

例如:

当前参数:

w=10w=10

梯度:

∂L∂w=4\frac{\partial L}{\partial w}=4

学习率:

η=0.1\eta=0.1

更新后:

w10−0.1×4w 10-0.1\times4

得到:

w=9.6w=9.6

6. 为什么不只使用梯度的符号?

这一问题是理解梯度下降的重要前提。

为什么不用:

sign⁡(∇L)\operatorname{sign}(\nabla L)

而要使用完整的梯度?


假设:

两个参数:

梯度:

∇L=(100,1)\nabla L=(100,1)

说明:

第一个方向离最优解非常远。

第二个方向离最优解已经很近。


如果只保留符号:

(1,1)(1,1)

那么:

两个方向会被同等对待。

训练效率会非常低。


梯度的大小包含了重要的信息:

  • 方向
  • 距离
  • 曲率信息

因此,梯度不仅告诉模型朝哪里走,还告诉模型走多远。


7. 为什么 SGD 有随机性,却仍然能够收敛?

完整损失:

L=1N∑i=1NliL= \frac1N \sum_{i=1}^N l_i

真实梯度:

∇L=1N∑i=1N∇li\nabla L= \frac1N \sum_{i=1}^N \nabla l_i

但是,每次训练只抽取一个小批量:

BB

于是:

g=1∣B∣∑i∈B∇lig= \frac1{|B|} \sum_{i\in B} \nabla l_i

由于是随机采样:

每个批次的梯度都不完全一样。

例如:

真实梯度:

(5,5)(5,5)

第一个批次:

(4,6)(4,6)

第二个批次:

(6,4)(6,4)

第三个批次:

(5,4)(5,4)

虽然存在波动,但是:

E[g]∇LE[g] \nabla L

也就是说:

随机梯度的期望等于真实梯度。

从长期来看,模型仍然沿着正确的方向移动。


8. 为什么神经网络需要反向传播?

假设:

一个两层网络:

x→h→yx \rightarrow h \rightarrow y

其中:

第一层:

h=f1(x,w1)h=f_1(x,w_1)

第二层:

y=f2(h,w2)y=f_2(h,w_2)

损失:

L(y)L(y)

现在需要求:

∂L∂w1\frac{\partial L}{\partial w_1}

但是:

损失函数并不直接依赖于:

w1w_1

而是:

w1→h→y→Lw_1 \rightarrow h \rightarrow y \rightarrow L

因此:

必须使用链式法则:

∂L∂w1∂L∂y×∂y∂h×∂h∂w1\frac{\partial L}{\partial w_1} \frac{\partial L}{\partial y} \times \frac{\partial y}{\partial h} \times \frac{\partial h}{\partial w_1}

这个梯度的传播过程:

前向传播:

x
↓

隐藏层

↓

输出层

↓

Loss

-------------------

反向传播:

Loss

↑

输出层

↑

隐藏层

↑

x

这就是反向传播。


9. PyTorch 是如何实现梯度的?

很多人会误以为:

loss.backward()

是在计算梯度。

其实不是。


真正的流程是:

第一步,前向传播:

y_hat = net(X)

第二步,自动构建计算图:

X
↓

Linear

↓

ReLU

↓

Linear

↓

CrossEntropyLoss

PyTorch 会自动记录:

  • 输入
  • 输出
  • 运算关系

第三步,调用:

loss.backward()

此时:

PyTorch 会从损失开始:

Loss

↑

Linear

↑

ReLU

↑

Linear

沿着计算图反向传播。


第四步,梯度被存储到:

parameter.grad

例如:

w.grad

b.grad

第五步,优化器更新参数:

optimizer.step()

等价于:

ww−η∂L∂ww w-\eta\frac{\partial L}{\partial w}

第六步,清空梯度:

optimizer.zero_grad()

因为 PyTorch 默认会累积梯度。


10. 从工程角度看,整个训练过程实际上只有六个步骤

数据

↓

DataLoader

↓

模型

↓

损失函数

↓

梯度

↓

优化器

↓

更新参数

↓

下一轮训练

D2L 第 3 章,其实就是在逐步封装这六个模块。

线性回归:

数据 → Linear → MSE → SGD

Softmax 回归:

数据 → Softmax → CrossEntropy → SGD

CNN:

数据 → Conv → CrossEntropy → Adam

Transformer:

数据 → Attention → CrossEntropy → AdamW

LLM:

Token → Transformer → CrossEntropy → AdamW

由此可以观察到一个现象:

后面的模型越来越复杂,但训练流程几乎没有变化。

变化的是:

  • 模型结构
  • 参数规模
  • 数据规模
  • 优化算法

不变的是:

Forward

↓

Loss

↓

Gradient

↓

Backward

↓

Optimizer

↓

Parameter Update

线性回归与 Softmax 回归不仅是两个具体模型,也用于建立深度学习训练系统的底层抽象。

在 CNN 和 Transformer 等模型中,梯度仍然承担相同作用:把预测误差转换成参数调整信号,并将该信号传递到网络中的每一个可学习参数。


关联文档

Yanche Blog

记录云原生、Linux、数据库等技术领域的学习心得,以及日常生活的思考与感悟。

© 2026 Yanche Blog. All rights reserved.

Powered by Astro