矩阵求导与自动微分:反向传播的 math 地基
三种形状
标量/向量互相求导,雅可比登场
四条恒等式
够用一辈子的求导公式
链式法则
矩阵形式与那个转置
手写反向传播
两层 MLP 从头推到尾
【开场场景】你搭好一个两层神经网络,敲下 loss.backward(),一秒钟后几百万个权重各自拿到了梯度。这一秒钟里发生了什么?答案只有四个字:链式法则。只不过当变量从"一个数"升级成"几百万个权重",链式法则必须写成矩阵形式,而矩阵乘法讲究顺序、还带转置。本章就是把这套"带转置的链式法则"讲透——它是 PyTorch、JAX、TensorFlow 共同的地基,也是"算法工程师"和"只会调包的人"之间最硬的一条分界线。
① 是什么:三种形状与雅可比矩阵
啥雅可比是一张"敏感度清单"
标量对向量:若 $f:\mathbb{R}^{n}\to\mathbb{R}$,把 $n$ 个偏导排成一个向量,就是梯度 $\frac{\partial f}{\partial x}=\left(\frac{\partial f}{\partial x_1},\ldots,\frac{\partial f}{\partial x_n}\right)^{\top}$,形状和 $x$ 一样。
向量对向量:若 $f:\mathbb{R}^{n}\to\mathbb{R}^{m}$,把"每个输出对每个输入"的偏导排成一张 $m\times n$ 的表,就是雅可比矩阵 $J$,其中 $J_{ij}=\frac{\partial f_i}{\partial x_j}$。第 $i$ 行,就是第 $i$ 个输出对所有输入的敏感度。
大白话:梯度回答"这个旋钮往哪拧,仪表读数升得最快";雅可比回答"这一整排旋钮,分别对这一整排仪表各有多大影响"。神经网络里,权重就是那排旋钮,损失就是那块仪表。
② 怎么想到的
思解题心法:先定形状,再查转置
先写维度。$\frac{\partial L}{\partial W}$ 的形状必须和 $W$ 一模一样。这是最硬的一条自检规则——一旦对不上,八成是漏了转置或者把外积写成了内积。
用微分法,别死记公式表。把 $f$ 的微分写成 $\mathrm{d}f=\sum_i g_i\,\mathrm{d}x_i$,那么 $\frac{\partial f}{\partial x}=g$。对矩阵同样成立:$\mathrm{d}f=\mathrm{tr}\!\left(G^{\top}\,\mathrm{d}X\right)$ 就意味着 $\frac{\partial f}{\partial X}=G$。
链式法则只记一句:$\frac{\partial L}{\partial x}=\left(\frac{\partial z}{\partial x}\right)^{\top}\frac{\partial L}{\partial z}$。那个转置不是谁拍脑袋规定的,是维度逼出来的。
证矩阵求导与自动微分的核心定理与公式
推导思路:①设 $f(x)=x^{\top}Ax=\sum_i\sum_j a_{ij}\,x_i x_j$,对第 $k$ 个分量求偏导,只有含 $x_k$ 的项能留下来,得 $\frac{\partial f}{\partial x_k}=\sum_j a_{kj}x_j+\sum_i a_{ik}x_i$。②第一项恰好是 $(Ax)_k$,第二项恰好是 $(A^{\top}x)_k$。③于是 $\frac{\partial f}{\partial x}=Ax+A^{\top}x=(A+A^{\top})x$;当 $A$ 对称时两项合并为 $2Ax$。④实战里取 $A=X^{\top}X$ 就能推出最小二乘的梯度 $\frac{\partial}{\partial w}\|Xw-y\|^{2}=2X^{\top}(Xw-y)$——线性回归的正规方程,就是令它等于零解出来的。
直觉把握:$x^{\top}Ax$ 是一个"二次碗"的高度,它的梯度告诉你碗壁往哪边最陡。之所以冒出 $(A+A^{\top})$ 而不是 $2A$,是因为 $x_i$ 与 $x_j$ 在二次型里成对出现,两个方向都要各算一次账。工程上,凡是"平方误差"形状的损失(MSE、最小二乘、岭回归),梯度里一定会蹦出一个 $2A^{\top}(\cdot)$——那个转置就是把"残差"从输出空间搬回参数空间的搬运工。
③ 完整解法:三个例题
④ 用途与案例
反向传播 = 本章公式的循环执行
所谓训练神经网络,就是从输出层往输入层,把 $\delta_{\ell}=\left(W_{\ell+1}^{\top}\delta_{\ell+1}\right)\odot\sigma'(z_{\ell})$ 和 $\frac{\partial L}{\partial W_{\ell}}=\delta_{\ell}a_{\ell-1}^{\top}$ 反复套用。看似神秘的 backward,拆开就这两行。
前向模式 vs 反向模式:JVP 与 VJP
前向模式算雅可比-向量积 $Jv$(一次前向拿一列),反向模式算向量-雅可比积 $v^{\top}J$(一次反向拿一行)。深度学习里损失是标量、参数上千万,一次反向就能拿到全部参数的梯度,所以框架一律选反向模式。
PyTorch autograd 的工程细节
backward() 沿动态计算图做 VJP 并累加到 .grad 上,所以每轮都要 zero_grad(),否则梯度越攒越大。推理时用 torch.no_grad() 关掉建图,能省一大截显存。
雅可比本身也是有用的:机器人学
机械臂的雅可比把"每个关节的角速度"映射成"末端的线速度"。要做轨迹规划和力控,就得实时求它、甚至求逆——这是雅可比矩阵最直观的一张工程面孔。
⑤ 延展
展知识衔接地图
往研究生走:雅可比是微分几何里"推前映射"的坐标表示;换坐标时它按 $J'=PJP^{-1}$ 变换,和线性代数里的相似矩阵是一套语言。
往 AI 走:再往上一步是二阶方法——Hessian 矩阵、以及不用显式存 Hessian 就能算的 Hessian-vector product(这正是牛顿法能用于大模型的原因)。JAX 把这套东西做成了三个原语:grad(反向)、jvp(前向)、vjp(向量-雅可比积),并且可以任意嵌套求高阶导数。想真正吃透自动微分,去把 JAX 的 autodiff cookbook 读一遍。
以为 $\frac{\partial (x^{\top}Ax)}{\partial x}$ 永远是 $2Ax$。只有 $A$ 对称才成立,一般情形是 $(A+A^{\top})x$。协方差矩阵对称所以没事,但随便一个方阵就不一定了。
链式法则忘写转置。$\frac{\partial L}{\partial x}=W^{\top}\frac{\partial L}{\partial z}$ 里那个 $\top$ 丢了,维度立刻对不上。检验办法:看形状——$\frac{\partial L}{\partial x}$ 必须和 $x$ 同形。
以为自动微分是在求符号表达式。不是。autograd 只是在计算图上按链式法则做数值乘法,它给你的是"某个具体输入点处的导数值",不是一条公式。这也是为什么它对 if 分支、循环全都照求不误。
练习
【基础】求 $f(x)=\|x\|^{2}=x^{\top}x$ 对 $x$ 的梯度。
查看思路与解答
把 $f$ 写成 $\sum_i x_i^{2}$,对第 $k$ 个分量求导只有 $x_k^{2}$ 项留存,得 $2x_k$,排成向量即 $\frac{\partial f}{\partial x}=2x$。这就是二次型公式在 $A=I$ 时的特例。卡住了?回到本章「四条恒等式」那一段,把 $A=I$ 代进去再推一遍。
【进阶】设 $z=Wx$,$W$ 是 $m\times n$ 的,损失为标量 $L$。已知 $\frac{\partial L}{\partial z}$ 是 $m$ 维向量,求 $\frac{\partial L}{\partial x}$ 并说明转置从哪来。
查看思路与解答
逐分量写:$z_i=\sum_j W_{ij}x_j$,故 $\frac{\partial z_i}{\partial x_j}=W_{ij}$,即雅可比 $\frac{\partial z}{\partial x}=W$。由链式法则 $\frac{\partial L}{\partial x_j}=\sum_i\frac{\partial L}{\partial z_i}W_{ij}$,右边正是 $\frac{\partial L}{\partial z}$ 与 $W$ 第 $j$ 列的点积,也就是 $\left(W^{\top}\frac{\partial L}{\partial z}\right)_j$。所以 $\frac{\partial L}{\partial x}=W^{\top}\frac{\partial L}{\partial z}$。转置是维度逼出来的:$W^{\top}$ 是 $n\times m$,乘上 $m$ 维向量才得到 $n$ 维的 $\frac{\partial L}{\partial x}$。卡住了?回到本章例题3的第②步,对着形状再走一遍。
【挑战】证明:当最后一层是 softmax、损失是多分类交叉熵时,有 $\frac{\partial L}{\partial z}=\hat{y}-y$,其中 $\hat{y}$ 是预测概率、$y$ 是 one-hot 标签。这是全站最值得亲手推一遍的公式。
查看思路与解答
设类别数为 $C$,$\hat{y}_i=\frac{e^{z_i}}{\sum_j e^{z_j}}$,损失 $L=-\sum_k y_k\log\hat{y}_k$。①先算 softmax 自身的导数:对 $i=k$ 有 $\frac{\partial \hat{y}_k}{\partial z_k}=\hat{y}_k(1-\hat{y}_k)$;对 $i\neq k$ 有 $\frac{\partial \hat{y}_k}{\partial z_i}=-\hat{y}_k\hat{y}_i$。②链式法则:$\frac{\partial L}{\partial z_i}=-\sum_k\frac{y_k}{\hat{y}_k}\cdot\frac{\partial \hat{y}_k}{\partial z_i}$。③把①的两类项分开:$\frac{\partial L}{\partial z_i}=-\frac{y_i}{\hat{y}_i}\hat{y}_i(1-\hat{y}_i)-\sum_{k\neq i}\frac{y_k}{\hat{y}_k}(-\hat{y}_k\hat{y}_i)=-y_i(1-\hat{y}_i)+\hat{y}_i\sum_{k\neq i}y_k$。④因 $y$ 是 one-hot,$\sum_k y_k=1$,故 $\sum_{k\neq i}y_k=1-y_i$,代入得 $\frac{\partial L}{\partial z_i}=-y_i+y_i\hat{y}_i+\hat{y}_i-\hat{y}_iy_i=\hat{y}_i-y_i$。这就是"logits 的梯度 = 预测减标签"的来历,也是为什么框架都把 softmax 和交叉熵合并成一个算子(数值更稳、梯度更简洁)。卡住了?难点全在第①步 softmax 的分情况求导,把 $C=2$ 的情形先手算一遍再回到一般情形。
- 用自己的话讲:梯度是"一个旋钮的敏感度",雅可比是"一整排旋钮的敏感度清单";反向传播就是把链式法则从后往前反复套。
- 举个反例(什么条件下不成立):$\frac{\partial (x^{\top}Ax)}{\partial x}$ 只有在 $A$ 对称时才等于 $2Ax$;链式法则少了转置,形状立刻崩掉。
- 哪里还说不清:$W^{\top}$ 那个转置,你能不看书、只靠维度对齐自己推出它必须存在吗?
① 雅可比 $J_{ij}=\frac{\partial f_i}{\partial x_j}$:第 $i$ 行是第 $i$ 个输出对所有输入的敏感度。
② 链式法则的矩阵形式:$\frac{\partial L}{\partial x}=W^{\top}\frac{\partial L}{\partial z}$,转置由维度唯一决定。
③ 反向传播就两行:回传 $\delta_{\ell}=\left(W_{\ell+1}^{\top}\delta_{\ell+1}\right)\odot\sigma'(z_{\ell})$,取参数梯度 $\frac{\partial L}{\partial W_{\ell}}=\delta_{\ell}a_{\ell-1}^{\top}$。
④ softmax + 交叉熵的梯度化简为 $\hat{y}-y$,是工程上最重要的一条捷径。