基础 · 02

微积分的几何直觉

导数是切线的斜率,梯度是「上山最陡」的方向。一篇文章把梯度下降——所有神经网络训练的引擎——画给你看。

13 min read

为什么 ML 离不开它

机器学习的训练过程,从最朴素的线性回归到 GPT,本质上都是同一件事:

定义一个表示「模型预测有多错」的数 LL,然后调整参数让它变小。

「调整参数让它变小」听起来抽象——但只要你能算出 LL 对每个参数的导数,你就知道每个参数往哪个方向动会让 LL 变小。整个深度学习的训练循环就两步:

  1. 算损失 LL 对所有参数的梯度 L\nabla L
  2. 把参数往 L-\nabla L 方向挪一小步。

这就是梯度下降。理解它需要的微积分,只是导数和链式法则两件事的几何化。这篇我们就把它们画出来。

导数:一点的斜率

导数 f(x0)f'(x_0) 就是函数 ffx0x_0 这个点的切线的斜率。

定义式:

f(x0)=limh0f(x0+h)f(x0)hf'(x_0) = \lim_{h \to 0} \frac{f(x_0 + h) - f(x_0)}{h}

公式里的「极限」「无穷小」让人头大,但几何上就是一句话:把切线斜率代数化

拖动下面的圆点感受一下:

-2-112drag the dot ↔

函数

f(x) = 0.3·(x³ − 2x)

位置

x = -1.30
f(x) = 0.12

导数(斜率)

f′(x) = 0.92

正 → 这里在上升

拖动小圆点。彩色那条线就是该点的切线——它的斜率就是导数。

几个值得留意的事实:

  • 导数 大于 0 → 函数在这里上升(往右走 ff 增加)。
  • 导数 小于 0 → 函数在这里下降
  • 导数 等于 0 → 切线水平 → 极大值、极小值或者鞍点。

最后一条是优化的核心:所有的最小值都满足 f(x)=0f'(x) = 0。所以要找最小值,就是去找导数等于零的地方。

梯度:上山最陡的方向

ML 里的损失函数不是 1 维的,而是依赖几千万、几亿个参数。一个 nn 元函数 L(w1,w2,,wn)L(w_1, w_2, \ldots, w_n) 没有「斜率」这种单一的数——但它有 nn偏导数:

Lwi\frac{\partial L}{\partial w_i}

意思就是「假装其他参数全冻住,只动 wiw_i,LL 的斜率是多少」。

把这些偏导数打包成一个向量,就是梯度:

L=(Lw1,  Lw2,  ,  Lwn)\nabla L = \left( \frac{\partial L}{\partial w_1},\; \frac{\partial L}{\partial w_2},\; \ldots,\; \frac{\partial L}{\partial w_n} \right)

这就是这篇最关键的一句话:

梯度 L\nabla L 指向 LL 在当前位置上升最快的方向,大小是上升的速率。

所以反过来,L-\nabla L 就是下降最快的方向——这就是「下山最陡的路」。

为什么是「最陡」?直观地说: 沿任意方向 u\mathbf{u}(单位向量)走一小步,LL 的变化率是 Lu\nabla L \cdot \mathbf{u}。两个向量点积在它们方向一致时最大,所以 u=L/L\mathbf{u} = \nabla L / |\nabla L| 时上升最快,u=L/L\mathbf{u} = -\nabla L / |\nabla L| 时下降最快。

还有一个免费的几何事实:梯度永远垂直于等高线。这一点在下面的动图里直接能看到。

梯度下降:下山的算法

知道了「最陡的下山方向」,算法就只剩一行:

wwηL(w)w \leftarrow w - \eta \cdot \nabla L(w)

η\eta学习率(learning rate)——一步迈多大。

但「迈多大」是个真问题。点一下画布换起点,拖一下学习率滑块感受:

损失函数

L(x, y) = 0.3·x² + 1.5·y²

椭圆形山谷,最小值在原点(紫色圆心)

当前轨迹

收敛到最小值

L(最终) = 0.000

✦ 点击画布换起点
✦ 拖动滑块改学习率
✦ 路径每次重新跑 30 步

紫色椭圆是等高线——同一圈上 L 相同。 负梯度永远垂直于等高线指向「内圈」——这就是下山的路。

三种典型情形:

  • η\eta 太小 → 每步几乎不动,一万步还没下到谷底。
  • η\eta 合适 → 沿着「最陡的弧线」平滑收敛。
  • η\eta 太大 → 一步直接跨过山谷,反弹到对面甚至越冲越远(发散)。

而且——注意上面这个椭圆形山谷:轨迹经常是 Z 字形的。原因是 yy 方向比 xx 方向陡得多,负梯度大部分指向「垂直于谷底的方向」,而不是「沿着谷底的方向」。这是普通梯度下降的老毛病,也是后来 momentum、Adam 等优化器要解决的问题。

链式法则:把误差传回去

神经网络是函数的层层嵌套。一个三层网络的输出大概长这样:

y^=f3(f2(f1(x;w1);w2);w3)\hat{y} = f_3\big(f_2\big(f_1(x;\, w_1);\, w_2\big);\, w_3\big)

想算 LL 对最深一层参数 w1w_1 的偏导,得穿过 f2f_2f3f_3 才能到 w1w_1。链式法则就是这件事的数学:

Lw1=Lf3f3f2f2f1f1w1\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial f_3} \cdot \frac{\partial f_3}{\partial f_2} \cdot \frac{\partial f_2}{\partial f_1} \cdot \frac{\partial f_1}{\partial w_1}

把它读作「敏感度的传递」会更直观:w1w_1 抖一下 → f1f_1 抖一下 → f2f_2 跟着抖 → f3f_3 跟着抖 → LL 跟着抖。每一段的「抖动放大倍数」就是局部的偏导,把它们乘起来就是端到端的敏感度。

这就是反向传播(backpropagation) 的全部秘密——从输出端往输入端,把局部导数一段一段乘回去。PyTorch、JAX 这些框架的核心其实就是: 自动帮你把这条乘法链算出来。

这个想法在前沿里