LLM WIKI · 课程精读

LEARNING UNIT · 01

矩阵计算与反向传播

从矩阵乘法的局部梯度出发,建立广播、归约、链式法则和 Jacobian 的统一视角。

已整理章节
12 节
单元来源
11 条视频
总时长
34:52
状态
已发布
学习位置
1 / 20
01

主题讲解 · 03:35

从单元素链式法则推导线性层输入梯度

学习目标

  • 说清 PyTorch 线性层为什么把前向写成 Y=XWTY=XW^T
  • 从一个输入元素 x23x_{23} 的依赖关系推导其梯度。
  • 把标量链式法则识别成矩阵乘法 dX=dYWdX=dY\,W
  • 用 shape 检查转置方向,而不是死记公式。

前置与衔接

本课默认你已经知道标量链式法则:

Lx=jLyjyjx.\frac{\partial L}{\partial x} = \sum_j \frac{\partial L}{\partial y_j} \frac{\partial y_j}{\partial x}.

这里的关键不是学习新的求导规则, 而是把大量结构相同的标量偏导重新装回矩阵。

为了贴合视频与 PyTorch 的权重存储约定, 设:

  • XRN×IX\in\mathbb{R}^{N\times I}:一批输入。
  • WRO×IW\in\mathbb{R}^{O\times I}:线性层权重。
  • YRN×OY\in\mathbb{R}^{N\times O}:线性层输出。
  • dY=L/YRN×OdY=\partial L/\partial Y\in\mathbb{R}^{N\times O}:上游梯度。

其中 NN 是样本数, II 是输入特征数, OO 是输出特征数。

核心讲解

1. 先固定前向约定

PyTorch 的线性层把每个输出神经元的一组权重存成 WW 的一行。

所以批量前向写为:

Y=XWT.Y=XW^T.

维度检查是:

(N×I)(I×O)=N×O.(N\times I)(I\times O)=N\times O.
图 1

在 PyTorch 线性层约定 Y=XWTY=XW^T 下,输入梯度的目标公式是 L/X=(L/Y)W∂L/∂X=(∂L/∂Y)W

原视频 · 00:00 ↗

画面给出的结论是:

dX=dYW.dX=dY\,W.

不要先背这个式子。

我们从一个元素的依赖路径把它推出来。

2. 梯度矩阵只是逐元素偏导的排列

dXdX 的第 ii 行第 kk 列就是:

(dX)ik=Lxik.(dX)_{ik}=\frac{\partial L}{\partial x_{ik}}.

因此 dXdX 必须与 XX 同形, 即 dXRN×IdX\in\mathbb{R}^{N\times I}

图 2

矩阵梯度 L/X∂L/∂X 按元素收集 L/xij∂L/∂x_{ij},其形状必须与 XX 相同。

原视频 · 00:30 ↗

这个“梯度与被求导张量同形”的不变量, 是后面检查公式最可靠的工具。

3. 追踪一个元素 x23x_{23}

Y=XWTY=XW^T, 输出元素满足:

yij=k=1IxikWjk.y_{ij} = \sum_{k=1}^{I}x_{ik}W_{jk}.

x23x_{23} 的样本下标是 2, 特征下标是 3。

它只会出现在输出的第 2 行, 并与 WW 第 3 列的元素配对。

图 3

x23x_{23} 位于 XX 的第 2 行第 3 列,在 XWTXW^T 中会与 WW 的第 3 列元素配对。

原视频 · 01:20 ↗

具体地, x23x_{23} 会影响:

  • y21y_{21},局部系数为 W13W_{13}
  • y22y_{22},局部系数为 W23W_{23}
  • y23y_{23},局部系数为 W33W_{33}
  • 若输出维更大,则继续影响同一行的其余 y2jy_{2j}
图 4

x23x_{23} 只影响同一输出行的 y21,y22,y23y_{21},y_{22},y_{23},对应系数依次来自 W13,W23,W33W_{13},W_{23},W_{33}

原视频 · 01:40 ↗

它不会影响 y1jy_{1j}y3jy_{3j}, 因为矩阵乘法不会混合不同样本行。

4. 只保留链式法则中的非零项

x23x_{23} 求导:

Lx23=jLy2jy2jx23.\frac{\partial L}{\partial x_{23}} = \sum_j \frac{\partial L}{\partial y_{2j}} \frac{\partial y_{2j}}{\partial x_{23}}.

而:

y2jx23=Wj3.\frac{\partial y_{2j}}{\partial x_{23}}=W_{j3}.

所以:

Lx23=jLy2jWj3.\frac{\partial L}{\partial x_{23}} = \sum_j \frac{\partial L}{\partial y_{2j}}W_{j3}.
图 5

L/x23∂L/∂x_{23} 只需累加三个受影响输出的上游梯度与局部导数乘积。

原视频 · 02:30 ↗

右侧正是 dYdY 第 2 行与 WW 第 3 列的内积。

5. 从一个元素推广到整个矩阵

一般地:

(dX)ik=j=1O(dY)ijWjk.(dX)_{ik} = \sum_{j=1}^{O}(dY)_{ij}W_{jk}.

这就是矩阵乘法 dYWdY\,W 的元素定义。

因此:

dX=dYW.\boxed{dX=dY\,W}.
图 6

L/x23∂L/∂x_{23} 等于 L/Y∂L/∂Y 的第 2 行与 WW 的第 3 列做内积,由此得到整体矩阵公式。

原视频 · 03:10 ↗

shape 再检查一次:

(N×O)(O×I)=N×I.(N\times O)(O\times I)=N\times I.

结果确实与 XX 同形。

6. 转置位置取决于前向写法

本课结论依赖前向约定 Y=XWTY=XW^T

如果另一份教材把权重存成 W~RI×O\widetilde W\in\mathbb{R}^{I\times O}, 并写成:

Y=XW~,Y=X\widetilde W,

那么输入梯度会写成:

dX=dYW~T.dX=dY\,\widetilde W^T.

两种公式没有矛盾。

它们只是权重坐标系不同。

跟练与练习

原视频练习

编者练习

XR4×5X\in\mathbb{R}^{4\times 5}WR7×5W\in\mathbb{R}^{7\times 5}, 前向为 Y=XWTY=XW^T, 且已知 dYR4×7dY\in\mathbb{R}^{4\times 7}。 请写出 dXdX 的矩阵公式与 shape, 并展开 (dX)14(dX)_{14} 的求和式。

查看参考答案

由前向约定可得:
dX=dYW.dX=dY\,W.
shape 为:
(4×7)(7×5)=4×5.(4\times 7)(7\times 5)=4\times 5.
因此 dXdXXX 同形。
目标元素为:
(dX)14=j=17(dY)1jWj4.(dX)_{14} = \sum_{j=1}^{7}(dY)_{1j}W_{j4}.
它是 dYdY 第 1 行与 WW 第 4 列的内积。

常见误区

  • 看到前向有 WTW^T,就机械地在反向也写 WTW^T
  • 忘记 PyTorch 存储的 WW shape 是 (O,I)(O,I)
  • x23x_{23} 错当成会影响所有输出行。
  • 展开链式法则时保留大量本来为零的依赖项。
  • 只看符号不检查矩阵乘法的内维是否相等。
  • 把本课的二维公式未经说明直接套到含额外批次维的张量;一般实现会把所有前导维视作样本维。

本课小结

  • Y=XWTY=XW^T,输入梯度是 dX=dYWdX=dY\,W
  • 单个 (dX)ik(dX)_{ik}dYdYii 行与 WWkk 列的内积。
  • 梯度与被求导输入同形,是检查转置方向的第一原则。
  • 下一课把同一套依赖追踪方法应用到权重 WW,推导 dW=dYTXdW=dY^T X
02

主题讲解 · 03:24

从共享权重路径推导线性层权重梯度

学习目标

  • 从一个权重元素 w23w_{23} 的计算路径推导其梯度。
  • 理解权重为何要累加一批样本的梯度贡献。
  • 把标量求和识别成 dW=dYTXdW=dY^T X
  • 用 shape 和索引同时检查转置位置。

前置与衔接

上一课从 x23x_{23} 出发, 得到线性层的输入梯度:

dX=dYW.dX=dY\,W.

本课仍采用相同前向约定:

Y=XWT.Y=XW^T.

张量形状为:

  • XRN×IX\in\mathbb{R}^{N\times I}
  • WRO×IW\in\mathbb{R}^{O\times I}
  • YRN×OY\in\mathbb{R}^{N\times O}
  • dYRN×OdY\in\mathbb{R}^{N\times O}

现在求的是权重梯度 dWdW, 它必须与 WW 同形, 即 dWRO×IdW\in\mathbb{R}^{O\times I}

核心讲解

1. 目标公式与形状检查

视频要解释的整体公式是:

dW=dYTX.\boxed{dW=dY^T X}.
图 1

对前向 Y=XWTY=XW^T,权重梯度满足 L/W=(L/Y)TX∂L/∂W=(∂L/∂Y)^T X

原视频 · 00:00 ↗

先只做 shape 检查:

dYTRO×N.dY^T\in\mathbb{R}^{O\times N}.

所以:

(O×N)(N×I)=O×I.(O\times N)(N\times I)=O\times I.

结果与 WW 同形。

这说明公式在维度上可行, 但还没有解释为什么要这样乘。

2. 权重梯度矩阵的含义

dWdW 的元素定义是:

(dW)jk=Lwjk.(dW)_{jk}=\frac{\partial L}{\partial w_{jk}}.
图 2

L/W∂L/∂W 由所有 L/wij∂L/∂w_{ij} 组成,输出形状与存储的权重矩阵 WW 一致。

原视频 · 00:20 ↗

因此推导整个矩阵, 只需要推导任意一个 wjkw_{jk}, 再观察它的行列索引如何排列。

视频选取 w23w_{23} 作为例子。

3. w23w_{23} 在前向中出现在哪里

w23w_{23} 在存储矩阵 WW 中位于第 2 行第 3 列。

因为前向使用 WTW^T, 它在 WTW^T 中位于第 3 行第 2 列。

图 3

WW 中的 w23w_{23}WTW^T 中位于第 3 行第 2 列,因此乘到 XX 的第 3 个特征。

原视频 · 00:40 ↗

由元素公式:

yij=k=1Ixikwjk,y_{ij} = \sum_{k=1}^{I}x_{ik}w_{jk},

可以看出 w23w_{23}

  • 固定输出特征下标 j=2j=2
  • 固定输入特征下标 k=3k=3
  • 对所有样本下标 ii 都会重复使用。

所以它会影响:

y12,y22,,yN2.y_{12},y_{22},\ldots,y_{N2}.

每条路径上的局部系数分别是:

x13,x23,,xN3.x_{13},x_{23},\ldots,x_{N3}.
图 4

w23w_{23} 与各样本的第三个输入特征相乘,并只影响输出的第二个特征。

原视频 · 01:40 ↗

这就是权重梯度要跨样本累加的根本原因: 同一个参数在一批样本中被重复使用。

4. 写出 w23w_{23} 的链式法则

只保留 w23w_{23} 真正影响的输出:

Lw23=i=1NLyi2yi2w23.\frac{\partial L}{\partial w_{23}} = \sum_{i=1}^{N} \frac{\partial L}{\partial y_{i2}} \frac{\partial y_{i2}}{\partial w_{23}}.

局部导数为:

yi2w23=xi3.\frac{\partial y_{i2}}{\partial w_{23}}=x_{i3}.

因此:

Lw23=i=1N(dY)i2Xi3.\frac{\partial L}{\partial w_{23}} = \sum_{i=1}^{N} (dY)_{i2}X_{i3}.
图 5

L/w23∂L/∂w_{23} 是所有样本对应上游梯度与第三输入特征的乘积之和。

原视频 · 02:40 ↗

这里的求和轴是样本轴 ii

输出特征 2 与输入特征 3 都被保留下来, 分别成为 dWdW 的行和列。

5. 把标量求和识别成矩阵乘法

dYTdY^T 的第 2 行是:

[(dY)12,(dY)22,,(dY)N2].\big[(dY)_{12},(dY)_{22},\ldots,(dY)_{N2}\big].

XX 的第 3 列是:

[X13,X23,,XN3]T.\big[X_{13},X_{23},\ldots,X_{N3}\big]^T.

两者内积正好是:

i(dY)i2Xi3.\sum_i(dY)_{i2}X_{i3}.
图 6

L/Y∂L/∂Y 转置后,第 2 行与 XX 第 3 列的内积正好给出 L/w23∂L/∂w_{23}

原视频 · 03:00 ↗

推广到任意 j,kj,k

(dW)jk=i=1N(dY)ijXik.(dW)_{jk} = \sum_{i=1}^{N}(dY)_{ij}X_{ik}.

这就是:

dW=dYTX.\boxed{dW=dY^T X}.

6. 三个梯度公式放在一起看

对:

Y=XWT,Y=XW^T,

反向传播得到:

dX=dYW,dX=dY\,W,

以及:

dW=dYTX.dW=dY^T X.

dXdX 保留样本轴与输入特征轴。

dWdW 消去样本轴, 保留输出特征轴与输入特征轴。

这比记忆“哪里加转置”更稳定。

7. 额外前导维的边界

二维公式把 NN 写成一个样本轴。

若输入形状是:

XRB×T×I,X\in\mathbb{R}^{B\times T\times I},

线性层会对每个 (b,t)(b,t) 位置共享同一个 WW

概念上可以先把 BBTT 合并成 N=BTN=BT, 再应用 dW=dYTXdW=dY^T X

实现中等价于对全部前导位置累加贡献。

跟练与练习

原视频练习

编者练习

XR5×4X\in\mathbb{R}^{5\times 4}WR3×4W\in\mathbb{R}^{3\times 4}, 前向为 Y=XWTY=XW^T。 请写出 dWdW 的 shape, 并展开 (dW)31(dW)_{31}

查看参考答案

dYR5×3dY\in\mathbb{R}^{5\times 3}
所以:
dW=dYTX.dW=dY^T X.
shape 检查:
(3×5)(5×4)=3×4.(3\times 5)(5\times 4)=3\times 4.
目标元素为:
(dW)31=i=15(dY)i3Xi1.(dW)_{31} = \sum_{i=1}^{5}(dY)_{i3}X_{i1}.
它累加五个样本对同一个共享参数 w31w_{31} 的贡献。

常见误区

  • w23w_{23}WWWTW^T 中的位置混为一谈。
  • 忘记共享权重会在所有样本位置重复使用。
  • 将求和误做在输入特征轴,而不是样本或前导位置轴。
  • 只凭 dYdYXX 的出现顺序写 dYXdY X,忽略内维不匹配。
  • 误以为公式中的求和意味着对 batch 取平均;反向默认是求和,是否平均由损失的 reduction 决定。
  • 在含序列维时只对 batch 求和,漏掉 token 位置也共享同一权重。

本课小结

  • Y=XWTY=XW^T,权重梯度是 dW=dYTXdW=dY^T X
  • (dW)jk(dW)_{jk} 累加所有样本位置的 (dY)ijXik(dY)_{ij}X_{ik}
  • 转置 dYdY 是为了让输出特征轴成为结果的行。
  • 下一课把矩阵乘法暂时放下,统一理解 ReLU、Sigmoid 与逐元素乘法的局部梯度算子。
03

主题讲解 · 02:13

用局部导数理解三类基础梯度算子

学习目标

  • 区分上游梯度 dYdY、局部导数与输入梯度 dXdX
  • 写出 ReLU 和 Sigmoid 的反向算子。
  • 写出逐元素乘法对两个输入的梯度。
  • 识别不可导点与广播场景的实现边界。

前置与衔接

前两课处理的是矩阵乘法:

Y=XWT.Y=XW^T.

矩阵乘法的难点在索引、转置和求和轴。

本课回到更基础的逐元素算子。

所有例子都服从同一个局部链式法则:

dX=dYYX.dX = dY\odot\frac{\partial Y}{\partial X}.

其中:

  • dY=L/YdY=\partial L/\partial Y 是后续节点传来的上游梯度。
  • Y/X\partial Y/\partial X 是当前算子的局部导数。
  • dX=L/XdX=\partial L/\partial X 是当前算子向前一节点传出的梯度。

符号 \odot 表示逐元素乘法。

核心讲解

1. 梯度算子处理的是计算图的一条局部边

视频把 ReLU 反向写成类似 relu_grad(X, Y, dY) → dX 的接口。

具体实现不一定真的需要同时保存 XXYY

接口想表达的是:

  • 读取能够决定局部导数的前向信息。
  • 读取上游梯度 dYdY
  • 产生输入梯度 dXdX
图 1

ReLU 梯度算子读取前向张量与上游梯度,输出对输入的梯度;核心是把 dYdY 乘上局部导数掩码。

原视频 · 00:20 ↗

梯度算子不负责重新计算整个损失。

它只完成当前节点的向量—雅可比积。

2. dY 与 dX 不只是一个数

XXYY 都是张量, 则:

dY=LY,dX=LX.dY=\frac{\partial L}{\partial Y}, \qquad dX=\frac{\partial L}{\partial X}.

它们分别把每个元素对标量损失 LL 的偏导收集成张量。

图 2

dY=L/YdY=∂L/∂Y 是从后续节点传回的上游梯度,dX=L/XdX=∂L/∂X 是本算子继续向前传播的结果。

原视频 · 00:40 ↗

dYdY 的 shape 与 YY 一致。

dXdX 的 shape 与 XX 一致。

这个形状规则同样适用于更复杂的算子。

3. ReLU:上游梯度乘一个门控掩码

ReLU 前向是:

Y=ReLU(X)=max(0,X).Y=\operatorname{ReLU}(X)=\max(0,X).

x>0x>0 时, 局部导数是 1。

x<0x<0 时, 局部导数是 0。

因此远离零点时:

dX=dY1[X>0].dX=dY\odot \mathbf{1}[X>0].
图 3

ReLU 的局部导数在正区间为 1、负区间为 0;零点不可导,实际实现必须约定一个次梯度。

原视频 · 01:00 ↗

直觉上:

  • 正区间保留上游梯度。
  • 负区间截断上游梯度。

零点边界

视频板书把条件写成 X0X\ge 0 时取 1。

但数学上 ReLU 在 x=0x=0 不可导。

因此真正的梯度算子必须为零点选择一个次梯度约定。

不同定义或实现可能选择不同值。

阅读框架源码或算子文档时, 应把“正区间公式”与“零点实现约定”分开。

4. Sigmoid:复用前向输出

Sigmoid 前向为:

Y=σ(X)=11+eX.Y=\sigma(X)=\frac{1}{1+e^{-X}}.

其局部导数可化为:

YX=Y(1Y).\frac{\partial Y}{\partial X} = Y(1-Y).

所以反向为:

dX=dYY(1Y).dX=dY\odot Y\odot(1-Y).
图 4

Sigmoid 可复用前向输出 YY,将局部导数写成 Y(1Y)Y(1-Y),从而得到 dX=dYY(1Y)dX=dY⊙Y⊙(1-Y)

原视频 · 01:40 ↗

这里复用 YY 有两个好处:

  • 公式更短。
  • 不必在反向重新计算指数函数。

工程实现是否保存 YY, 还要在显存占用与重计算成本之间权衡。

本课只确定数学依赖, 不假定某个框架一定采用哪种缓存策略。

5. 逐元素乘法:每个输入都有一条梯度边

设:

Y=X1X2.Y=X_1\odot X_2.

局部导数分别为:

YX1=X2,YX2=X1.\frac{\partial Y}{\partial X_1}=X_2, \qquad \frac{\partial Y}{\partial X_2}=X_1.

所以:

dX1=dYX2,dX_1=dY\odot X_2,
dX2=dYX1.dX_2=dY\odot X_1.
图 5

逐元素乘法 Y=X1X2Y=X_1⊙X_2 对两个输入分别返回 dX1=dYX2dX_1=dY⊙X_2dX2=dYX1dX_2=dY⊙X_1

原视频 · 02:00 ↗

“对某个输入求导时保留另一个输入” 是乘法法则在逐元素张量上的直接应用。

6. 为什么这些公式看起来都是逐元素乘法

ReLU、Sigmoid 和同形状逐元素乘法都没有跨位置混合元素。

因此某个输出位置只依赖同位置输入。

它们的雅可比矩阵是对角结构。

向量—雅可比积就可以退化成逐元素乘法, 无需显式构造雅可比矩阵。

矩阵乘法则不同。

一个输出元素依赖一整行和一整列, 所以反向中出现新的矩阵乘法与归约。

7. 广播是本课公式的重要边界

上述乘法梯度默认 X1X_1X2X_2 同形, 没有发生广播。

若前向中某个输入被广播, 局部乘法之后还要把梯度归约回该输入的原 shape。

例如标量 aa 与向量 xx 相乘:

y=ax.y=a x.

aa 的梯度不是一个向量, 而是:

da=i(dyixi).da=\sum_i(dy_i x_i).

后两课会系统解释这种“前向广播、反向归约”。

跟练与练习

原视频练习

编者练习

设: z=σ(x),y=zm,z=\sigma(x), \qquad y=z\odot m, 已知上游梯度 dydy。 请写出 dzdzdxdx, 并说明反向需要哪些前向量。

查看参考答案

由逐元素乘法:
dz=dym.dz=dy\odot m.
再经过 Sigmoid:
dx=dzz(1z).dx = dz\odot z\odot(1-z).
合并得:
dx=dymz(1z).dx = dy\odot m\odot z\odot(1-z).
数学上需要 mm 和 Sigmoid 输出 zz
若没有保存 zz
也可以由 xx 重算,
但那是缓存与重计算的工程选择。

常见误区

  • dYdY 当成当前算子的局部导数。
  • 忘记 dXdX 还要乘上游梯度,单独写 Y/X\partial Y/\partial X
  • 把 ReLU 在零点的次梯度约定说成唯一数学导数。
  • 将 Sigmoid 导数错写成 X(1X)X(1-X);可复用的是输出 YY
  • 对两输入乘法只返回一个梯度,遗漏另一条输入边。
  • 在发生广播时仍原样返回逐元素乘积,忽略归约回输入 shape。

本课小结

  • 局部反向的统一结构是“上游梯度乘局部导数”。
  • ReLU 用门控掩码,Sigmoid 可复用 Y(1Y)Y(1-Y)
  • 逐元素乘法需要分别计算两个输入的梯度。
  • 零点不可导与广播归约都是公式之外必须明确的边界。
  • 下一课从线性层偏置出发,具体推导广播为何在反向变成求和。
04

主题讲解 · 03:01

线性层偏置梯度为何是按列求和

学习目标

  • 看懂线性层偏置在样本轴上的广播。
  • 从单样本特例推导多样本的偏置梯度。
  • 解释为什么二维场景中 dbdb 等于 dYdY 按列求和。
  • 区分“本课的 dim=0”与一般广播归约规则。

前置与衔接

前一课说明: 逐元素算子先把上游梯度乘局部导数。

若前向没有改变 shape, 局部结果通常可以直接作为输入梯度。

线性层偏置不同。

前向会把一个偏置向量重复加到多个样本行:

Y=XWT+b.Y=XW^T+b.

因此同一个偏置元素参与了多条输出路径。

反向必须把这些路径的贡献合并起来。

本课先限定二维线性层:

  • XRN×IX\in\mathbb{R}^{N\times I}
  • WRO×IW\in\mathbb{R}^{O\times I}
  • bROb\in\mathbb{R}^{O}
  • YRN×OY\in\mathbb{R}^{N\times O}

核心讲解

1. 偏置如何进入线性层

先计算:

Z=XWT.Z=XW^T.

其中 ZZ 的每一行都是一个样本的 OO 维输出。

再把同一个偏置向量 bb 加到每一行:

yij=zij+bj.y_{ij}=z_{ij}+b_j.
图 1

线性层 Y=XWT+bY=XW^T+b 将一维偏置 bb 广播到每个样本行的对应输出特征。

原视频 · 00:20 ↗

这里的两个索引很重要:

  • ii 表示样本。
  • jj 表示输出特征。

bjb_j 不随样本 ii 改变。

所以同一个参数会被所有样本共享。

2. 先看只有一个样本的特例

N=1N=1, 则:

yj=zj+bj.y_j=z_j+b_j.

对任意 bjb_j

yjbj=1.\frac{\partial y_j}{\partial b_j}=1.

且其他输出分量对 bjb_j 的导数为 0。

于是:

Lbj=Lyj.\frac{\partial L}{\partial b_j} = \frac{\partial L}{\partial y_j}.

向量形式为:

db=dY.db=dY.
图 2

只有一个样本行时,每个偏置分量只被使用一次,因此 L/b=L/Y∂L/∂b=∂L/∂Y

原视频 · 01:00 ↗

这个结论只在偏置没有被多个样本重复使用时成立。

3. 多样本时同一个偏置被重复使用

N>1N>1 时, bjb_j 出现在输出第 jj 列的每一行:

y1j=z1j+bj,y_{1j}=z_{1j}+b_j,
y2j=z2j+bj,y_{2j}=z_{2j}+b_j,
\ldots
yNj=zNj+bj.y_{Nj}=z_{Nj}+b_j.
图 3

XX 有多行时,同一个 bjb_j 被复制到输出第 jj 列的每一行,反向必须合并这些贡献。

原视频 · 01:40 ↗

前向看起来像把 bjb_j 复制了 NN 份。

但参数存储中仍只有一个 bjb_j

反向要把这 NN 条使用路径的梯度加回同一个参数槽位。

4. 用标量链式法则推导 dbjdb_j

因为 bjb_j 影响所有 yijy_{ij}, 有:

Lbj=i=1NLyijyijbj.\frac{\partial L}{\partial b_j} = \sum_{i=1}^{N} \frac{\partial L}{\partial y_{ij}} \frac{\partial y_{ij}}{\partial b_j}.

而:

yijbj=1.\frac{\partial y_{ij}}{\partial b_j}=1.

所以:

Lbj=i=1N(dY)ij.\frac{\partial L}{\partial b_j} = \sum_{i=1}^{N}(dY)_{ij}.
图 4

L/b1∂L/∂b_1 等于输出第一列所有上游梯度之和,因为各 yi1y_{i1}b1b_1 的局部导数都是 1。

原视频 · 02:00 ↗

这不是额外规定。

它只是共享参数的链式法则。

5. 矩阵形式就是按列求和

dYdY 的形状为:

dYRN×O.dY\in\mathbb{R}^{N\times O}.

要求:

dbRO.db\in\mathbb{R}^{O}.

所以要消去样本轴, 保留输出特征轴:

db=sum(dY,dim=0).\boxed{ db=\operatorname{sum}(dY,\mathrm{dim}=0) }.
图 5

对二维 YRN×DY\in\mathbb{R}^{N\times D}bRDb\in\mathbb{R}^{D},偏置梯度是 dYdY 沿样本轴求和,即 db=sum(dY,dim=0)db=\operatorname{sum}(dY,\,\mathrm{dim}=0)

原视频 · 02:40 ↗

“按列求和”是从矩阵外观看。

“沿 dim=0 归约”是从轴编号看。

两种说法描述的是同一个操作。

6. 为什么不是取平均

链式法则要求累加同一参数的全部使用路径。

因此偏置反向本身是求和。

训练代码中有时会观察到梯度带有 1/N1/N

那通常来自损失函数先对 batch 做了 mean reduction:

L=1NiLi.L=\frac{1}{N}\sum_i L_i.

此时 dYdY 已经包含 1/N1/N

偏置梯度算子仍然只是对收到的 dYdY 求和。

不要把损失的平均策略混入偏置算子的局部定义。

7. dim=0 只是当前二维布局的结论

本课中:

Y.shape=(N,O),b.shape=(O).Y.shape=(N,O), \qquad b.shape=(O).

bb 在样本轴 0 上被广播, 所以反向沿轴 0 求和。

若输出还有更多前导维, 例如:

Y.shape=(B,T,O),Y.shape=(B,T,O),

同一个 bROb\in\mathbb{R}^{O} 会在 BBTT 两个轴上重复。

那么:

db=b,tdYb,t,:.db=\sum_{b,t}dY_{b,t,:}.

也就是同时归约所有前导广播轴。

因此真正通用的规则不是“偏置永远 dim=0”, 而是“沿偏置被广播的轴求和”。

8. keepdim 取决于原始偏置 shape

若偏置存成一维:

b.shape=(O),b.shape=(O),

对二维 dYdY 沿 dim=0 求和后自然得到 (O)(O)

若偏置存成:

b.shape=(1,O),b.shape=(1,O),

则为了直接恢复同形结果, 可以在求和时保留被归约维:

db=sum(dY,dim=0,keepdim=True).db=\operatorname{sum}(dY,\mathrm{dim}=0,\mathrm{keepdim=True}).

keepdim 不是梯度数值规则, 而是结果 shape 的表达选择。

跟练与练习

原视频练习

编者练习

设: Y.shape=(2,3,4),b.shape=(4).Y.shape=(2,3,4), \qquad b.shape=(4). 前向为 Y=Z+bY=Z+b。 若 dYdY 已知, 请指出 bb 在哪些轴广播, 并写出 dbdb 的归约公式与 shape。

查看参考答案

b.shape=(4)b.shape=(4)Y.shape=(2,3,4)Y.shape=(2,3,4) 从尾维对齐,
可视为:
b.shape=(1,1,4).b.shape=(1,1,4).
bb 在轴 0 与轴 1 上扩展。
因此:
db=sum(dY,dim=(0,1)).db = \operatorname{sum}(dY,\mathrm{dim}=(0,1)).
结果 shape 为:
(4).(4).
若希望中间结果保持 (1,1,4)(1,1,4)
可设置 keepdim,
最后再按原始偏置表示恢复 shape。

常见误区

  • 单样本得到 db=dYdb=dY 后,直接照搬到多样本。
  • 说“广播会复制参数”,误以为参数存储真的产生多个独立副本。
  • 把偏置梯度写成对输出特征轴求和,导致结果只剩一个标量。
  • 把反向求和与损失函数的 batch mean 混为一谈。
  • 把二维布局的 dim=0 当成所有张量布局下的固定规则。
  • 不检查原始偏置是一维 (O)(O) 还是保留轴的 (1,O)(1,O)

本课小结

  • 线性层偏置在每个样本行重复使用。
  • 单样本时 db=dYdb=dY,多样本时要累加所有共享路径。
  • Y.shape=(N,O)Y.shape=(N,O)b.shape=(O)b.shape=(O),有 db=sum(dY,dim=0)db=\operatorname{sum}(dY,\mathrm{dim}=0)
  • 通用判断是沿前向广播轴归约,而不是死记某个 axis 编号。
  • 下一课把这个结论推广为任意 shape 的“前向广播、反向归约”规则。
05

主题讲解 · 03:23

从广播规则反推梯度归约轴

学习目标

  • 按尾维对齐规则判断两个 shape 是否可广播。
  • 计算广播后的输出 shape。
  • 从输入的扩展轴反推出反向的归约轴。
  • 正确处理补前导 1、keepdim 与局部导数。

前置与衔接

上一课从线性层偏置得到:

b.shape=(O),Y.shape=(N,O),b.shape=(O), \qquad Y.shape=(N,O),

前向在样本轴广播, 反向就沿样本轴求和。

本课把它推广到任意逐元素广播。

最重要的形状不变量是:

LA.shape=A.shape,\frac{\partial L}{\partial A}.shape=A.shape,
LB.shape=B.shape.\frac{\partial L}{\partial B}.shape=B.shape.

广播会让中间局部梯度拥有输出 shape。

归约负责把它恢复为每个原输入的 shape。

核心讲解

1. “反向归约”来自值被重复使用

以前向逐元素加法为例:

Y=A+B.Y=A+B.

若没有广播, 每个输入元素只对应一个输出元素。

AA 的某个维度为 1, 而输出该维度大于 1, 这个输入元素会沿该轴被重复使用。

反向时, 所有重复使用路径都指回同一个输入元素。

所以它们的梯度必须求和。

图 1

自动微分返回的输入梯度必须与原输入形状一致;前向广播复制出的多条路径,在反向需要归约回原形状。

原视频 · 00:20 ↗

“广播的反向是归约” 并不是把前向数值操作真正求逆。

更准确地说, 广播的线性复制映射在反向中的伴随操作是累加。

2. 一个可手算的二维例子

设:

A.shape=(2,1),A.shape=(2,1),
B.shape=(3).B.shape=(3).

从尾维对齐时, BB 可视为:

B.shape=(1,3).B.shape=(1,3).

前向中:

  • AA 的第二轴从 1 扩展到 3。
  • BB 的第一轴从 1 扩展到 2。
  • 输出 shape 为 (2,3)(2,3)
图 2

形状 (2,1)(2,1) 的列向量与形状 (3,)(3,) 的向量相加时,二者分别扩展为 (2,3)(2,3) 后逐元素相加。

原视频 · 00:40 ↗

若是加法, 局部梯度先得到与 YY 同形的 dYdY

AA

dA=sum(dY,dim=1,keepdim=True).dA=\operatorname{sum}(dY,\mathrm{dim}=1,\mathrm{keepdim=True}).

结果 shape 为 (2,1)(2,1)

BB

dB=sum(dY,dim=0).dB=\operatorname{sum}(dY,\mathrm{dim}=0).

结果 shape 为 (3)(3)

两个输入的归约轴不同, 因为它们在前向扩展的轴不同。

3. 广播比较必须从尾维开始

比较两个 shape 时:

  1. 从最右侧维度开始对齐。
  2. 较短的 shape 在左侧补 1。
  3. 再逐维判断是否兼容。

例如:

A.shape=(a,b,c),A.shape=(a,b,c),
B.shape=(d,a,1,b,c).B.shape=(d,a,1,b,c).

AA 左侧补 1:

Aaligned.shape=(1,1,a,b,c).A_{\mathrm{aligned}}.shape=(1,1,a,b,c).
图 3

比较广播形状时从尾维向前对齐;较短形状可在左侧补 1,再逐维判断兼容性。

原视频 · 01:40 ↗

“低维向高维对齐”这句话容易含糊。

准确规则是: 按尾维对齐, 缺失的前导维视为 1。

不能把短 shape 随意对到高 rank 张量的中间位置。

4. 逐维兼容条件与输出 shape

对每个已对齐维, 只有两类情况兼容:

  • 两边大小相等。
  • 至少一边大小为 1。

若兼容, 输出该维大小取两者较大值。

对上例:

(1,1,a,b,c)(1,1,a,b,c)

与:

(d,a,1,b,c)(d,a,1,b,c)

广播结果为:

Y.shape=(d,a,a,b,c).Y.shape=(d,a,a,b,c).
图 4

每个对齐维必须相等或至少一边为 1;兼容维的输出大小取两边较大值。

原视频 · 02:00 ↗

如果某个对齐维既不相等, 也没有任何一边为 1, 广播就应报 shape 不兼容。

5. 从扩展轴直接读出归约轴

仍看:

Aaligned.shape=(1,1,a,b,c),A_{\mathrm{aligned}}.shape=(1,1,a,b,c),
B.shape=(d,a,1,b,c),B.shape=(d,a,1,b,c),
Y.shape=(d,a,a,b,c).Y.shape=(d,a,a,b,c).

AA

  • 轴 0 从 1 扩展为 dd
  • 轴 1 从 1 扩展为 aa
  • 因此对局部梯度沿轴 (0,1)(0,1) 求和。

BB

  • 轴 2 从 1 扩展为 aa
  • 因此对局部梯度沿轴 2 求和。
图 5

某输入在哪些轴由 1 扩展成更大尺寸,反向就沿哪些轴对局部梯度求和,再恢复该输入的原始形状。

原视频 · 02:20 ↗

若当前算子是加法, 局部梯度就是 dYdY

于是:

dAaligned=sum(dY,dim=(0,1),keepdim=True),dA_{\mathrm{aligned}} = \operatorname{sum} (dY,\mathrm{dim}=(0,1),\mathrm{keepdim=True}),
dB=sum(dY,dim=2,keepdim=True).dB = \operatorname{sum} (dY,\mathrm{dim}=2,\mathrm{keepdim=True}).

随后把 dAaligneddA_{\mathrm{aligned}} 的两个补位前导轴移除, 恢复 A.shape=(a,b,c)A.shape=(a,b,c)

6. keepdim 的职责

BB 的原 shape 是:

(d,a,1,b,c).(d,a,1,b,c).

它在轴 2 本来就有一个显式的大小 1 维。

若对轴 2 求和时不保留维度, 结果会变成:

(d,a,b,c).(d,a,b,c).

这与 BB 不同形。

设置 keepdim=True 后, 结果保持:

(d,a,1,b,c).(d,a,1,b,c).

keepdim 处理的是 shape, 不是是否求和。

对由“补前导 1”产生的虚拟轴, 可先保留维度完成统一归约, 再 reshape 或移除补位轴回到原 rank。

7. 一套可执行的反向步骤

对任意支持广播的逐元素算子, 可以按以下顺序推导某个输入 AA 的梯度:

  1. 记录 AA 的原始 shape。
  2. 将它左侧补 1,与输出 shape 尾维对齐。
  3. 先计算该算子对 AA 的局部梯度。
  4. 找出 AA 的对齐维为 1、而输出对应维大于 1 的轴。
  5. 沿这些轴求和,并暂时 keepdim。
  6. 移除只为对齐而补出的前导轴。
  7. 检查最终梯度 shape 与 AA 原 shape 完全一致。

这类操作常被实现为 sum_to_size 或 unbroadcast。

名称可以不同, 核心都是“累加到原 shape”。

8. 先乘局部导数,再做 unbroadcast

“反向归约”不能代替当前算子的局部导数。

若:

Y=AB,Y=A\odot B,

那么对 AA 的输出形状局部梯度先是:

GA=dYB.G_A=dY\odot B.

AA 在前向发生广播, 再对 GAG_A 做 sum-to-shape:

dA=sum_to_shape(GA,A.shape).dA=\operatorname{sum\_to\_shape}(G_A,A.shape).

BB 同理:

GB=dYA,G_B=dY\odot A,
dB=sum_to_shape(GB,B.shape).dB=\operatorname{sum\_to\_shape}(G_B,B.shape).

只有加法的局部导数为 1, 才可以直接从 dYdY 开始归约。

9. 线性层偏置只是一般规则的特例

对:

Y=XWT+b,Y=XW^T+b,

若:

Y.shape=(N,O),b.shape=(O),Y.shape=(N,O), \qquad b.shape=(O),

对齐后的偏置 shape 是:

(1,O).(1,O).

它在轴 0 从 1 扩展为 NN, 所以:

db=sum(dY,dim=0).db=\operatorname{sum}(dY,\mathrm{dim}=0).
图 6

线性层偏置是广播规则的特例:偏置在样本轴重复,故其梯度沿样本轴求和。

原视频 · 03:00 ↗

这正是上一课的结论。

一般广播规则解释了为什么是该轴, 而不是要求记住一个固定 dim 编号。

跟练与练习

原视频练习

编者练习

设: A.shape=(3,1,5),A.shape=(3,1,5), B.shape=(2,1,4,5),B.shape=(2,1,4,5), 前向为: Y=A+B.Y=A+B. 请回答:

  1. AA 对齐后的 shape 是什么?
  2. Y.shapeY.shape 是什么?
  3. dAdAdBdB 分别沿哪些轴归约?
查看参考答案

AA 左侧补 1 后为:
Aaligned.shape=(1,3,1,5).A_{\mathrm{aligned}}.shape=(1,3,1,5).
与:
B.shape=(2,1,4,5)B.shape=(2,1,4,5)
逐维比较,
得到:
Y.shape=(2,3,4,5).Y.shape=(2,3,4,5).
AA 在轴 0 由 1 扩展到 2,
在轴 2 由 1 扩展到 4,
所以:
dAaligned=sum(dY,dim=(0,2),keepdim=True).dA_{\mathrm{aligned}} = \operatorname{sum} (dY,\mathrm{dim}=(0,2),\mathrm{keepdim=True}).
再移除补出的前导轴,
恢复 dA.shape=(3,1,5)dA.shape=(3,1,5)
BB 在轴 1 由 1 扩展到 3,
所以:
dB=sum(dY,dim=1,keepdim=True).dB = \operatorname{sum} (dY,\mathrm{dim}=1,\mathrm{keepdim=True}).
结果 shape 为 (2,1,4,5)(2,1,4,5)

常见误区

  • 从左侧开始对齐 shape,而不是从尾维开始。
  • 把较短 shape 的 1 随意插到中间,而不是只补在左侧。
  • 认为所有不相等维都能广播;必须至少一边为 1。
  • 只按 rank 差归约,漏掉原 shape 中本来就为 1 的扩展轴。
  • 无条件去掉求和维,导致梯度与原输入不同形。
  • 把“广播的反向是归约”理解成任何算子都只需对 dYdY 求和。
  • 死记偏置 dim=0,忽略轴编号取决于实际布局。

本课小结

  • 广播按尾维对齐,较短 shape 在左侧补 1。
  • 对齐维相等或至少一边为 1 才兼容,输出维取较大值。
  • 输入在哪些轴由 1 扩展,反向就沿哪些轴累加局部梯度。
  • keepdim 与移除补位轴共同保证梯度恢复原 shape。
  • 一般流程是先计算局部导数,再 sum-to-shape。
  • 线性层偏置梯度只是这套规则的一个二维特例。
06

主题讲解 · 03:34

线性型与二次型的梯度从哪里来

学习目标

  • 从逐元素展开推导线性型 aTxa^Tx 的梯度。
  • 解释二次型中一个变量为何同时出现在行项与列项。
  • 证明对称矩阵下 x12xTAx=Ax\nabla_x\frac12x^TAx=Ax
  • 说清非对称矩阵时正确的梯度边界。

前置与衔接

本课处理两个输出都是标量的函数。

x,aRnx,a\in\mathbb{R}^{n} 为列向量, ARn×nA\in\mathbb{R}^{n\times n}

对标量函数 y(x)y(x), 本课把梯度写成列向量:

xy=[y/x1y/xn].\nabla_x y = \begin{bmatrix} \partial y/\partial x_1\\ \vdots\\ \partial y/\partial x_n \end{bmatrix}.

这个约定决定公式的朝向。

后续遇到行梯度记号时, 同一组偏导会整体转置。

核心讲解

1. 两条常用结论

线性型为:

y=aTx.y=a^Tx.

其梯度为:

xy=a.\nabla_x y=a.

二次型为:

y=12xTAx.y=\frac12x^TAx.

A=ATA=A^T 时:

xy=Ax.\nabla_x y=Ax.
图 1

线性型 y=aTxy=a^Tx 的梯度是 aa;对称矩阵 AA 的二次型 y=12xTAxy=\frac12x^TAx 的梯度是 AxAx

原视频 · 00:20 ↗

这两条公式分别对应标量线性函数和二次函数的向量推广。

但二次型结论多了一个关键前提: AA 必须对称。

2. 线性型按元素展开

展开:

y=aTx=i=1naixi.y = a^Tx = \sum_{i=1}^{n}a_ix_i.

对任意 xkx_k

yxk=ak.\frac{\partial y}{\partial x_k}=a_k.

把所有分量按 xx 的原顺序排列:

xy=[a1an]=a.\nabla_x y = \begin{bmatrix} a_1\\ \vdots\\ a_n \end{bmatrix} =a.
图 2

aTxa^Tx 展开为 iaixi\sum_i a_i x_i 后,每个分量偏导为 aia_i,按原位组成列梯度 aa

原视频 · 01:00 ↗

这里没有跨分量求和的复杂性。

xkx_k 只在 akxka_kx_k 中出现一次。

3. 二次型中的变量会出现两次

二次型可写为:

y=12i=1nj=1nxiAijxj.y = \frac12 \sum_{i=1}^{n} \sum_{j=1}^{n} x_iA_{ij}x_j.

目标变量 xkx_k 有两种出现方式:

  • 作为左侧因子 xix_i,即 i=ki=k
  • 作为右侧因子 xjx_j,即 j=kj=k
图 3

二次型把行向量 xTx^T、矩阵 AA 与列向量 xx 相乘,目标分量会同时出现在左、右两个 xx 中。

原视频 · 01:20 ↗

因此对 xkx_k 求导时, 要同时收集矩阵第 kk 行与第 kk 列对应的路径。

这也是二次型比线性型多出 ATA^T 的根源。

4. 先处理对角平方项

x2x_2 为例, 对角项是:

12x2A22x2=12A22x22.\frac12x_2A_{22}x_2 = \frac12A_{22}x_2^2.

x2x_2 求导:

x2(12A22x22)=A22x2.\frac{\partial}{\partial x_2} \left( \frac12A_{22}x_2^2 \right) = A_{22}x_2.
图 4

x2x_2 求导时,对角项 12A22x22\frac12 A_{22}x_2^2 贡献 A22x2A_{22}x_2

原视频 · 01:40 ↗

前面的 1/21/2 与平方求导产生的 2 抵消。

5. 再处理成对交叉项

x2x_2 的一对交叉项例如:

12x2A21x112x1A12x2.\frac12x_2A_{21}x_1 \quad\text{与}\quad \frac12x_1A_{12}x_2.

它们对 x2x_2 的贡献是:

12A21x1+12A12x1.\frac12A_{21}x_1 + \frac12A_{12}x_1.

AA 对称, 则 A12=A21A_{12}=A_{21}, 两项合并为:

A21x1.A_{21}x_1.

其他交叉项同理。

图 5

x2x_2 对应的行项与列项成对出现;当 AA 对称时,A2jA_{2j}Aj2A_{j2} 可合并。

原视频 · 02:20 ↗

于是:

yx2=A21x1+A22x2+A23x3+.\frac{\partial y}{\partial x_2} = A_{21}x_1+A_{22}x_2+A_{23}x_3+\cdots.

这正是 AxAx 的第二个分量。

6. 推广到全部分量

对任意 kk

yxk=jAkjxj,A=AT.\frac{\partial y}{\partial x_k} = \sum_j A_{kj}x_j, \qquad A=A^T.

把所有分量组合:

x(12xTAx)=Ax.\boxed{ \nabla_x \left( \frac12x^TAx \right) =Ax }.
图 6

合并对角项和成对交叉项后,y/x2\partial y/\partial x_2 正好是 AxAx 的第二个分量,推广得 xy=Ax\nabla_x y=Ax

原视频 · 03:00 ↗

7. 非对称矩阵时不能直接写 Ax

这是视频已提示、但值得单独写清的边界。

AA 不对称, 逐元素推导得到:

x(12xTAx)=12(A+AT)x.\boxed{ \nabla_x \left( \frac12x^TAx \right) = \frac12(A+A^T)x }.

因为同一对交叉项分别贡献 AkjA_{kj}AjkA_{jk}

也可以注意:

xTAx=xT(A+AT2)x.x^TAx = x^T \left( \frac{A+A^T}{2} \right) x.

AA 的反对称部分不贡献该标量二次型。

A=ATA=A^T 时, 一般公式才化简为 AxAx

8. 用微分做一次独立复核

以下是编者补充, 用于检查逐元素推导:

dy=12d(xTAx).dy = \frac12\,d(x^TAx).

乘积法则给出:

dy=12(dx)TAx+12xTAdx.dy = \frac12(dx)^TAx + \frac12x^TA\,dx.

把两项都写成“某个列向量的转置乘 dxdx”:

dy=[12(A+AT)x]Tdx.dy = \left[ \frac12(A+A^T)x \right]^T dx.

由梯度定义 dy=(xy)Tdxdy=(\nabla_x y)^Tdx, 再次得到:

xy=12(A+AT)x.\nabla_x y = \frac12(A+A^T)x.

跟练与练习

原视频练习

编者练习

设: A=[1243],x=[x1x2],A= \begin{bmatrix} 1&2\\ 4&3 \end{bmatrix}, \qquad x= \begin{bmatrix} x_1\\ x_2 \end{bmatrix}, 且: y=12xTAx.y=\frac12x^TAx. 请写出 xy\nabla_x y, 并说明为什么不能直接写 AxAx

查看参考答案

因为 AA 不对称,
使用一般公式:
xy=12(A+AT)x.\nabla_x y = \frac12(A+A^T)x.
有:
12(A+AT)=[1333].\frac12(A+A^T) = \begin{bmatrix} 1&3\\ 3&3 \end{bmatrix}.
因此:
xy=[x1+3x23x1+3x2].\nabla_x y = \begin{bmatrix} x_1+3x_2\\ 3x_1+3x_2 \end{bmatrix}.
直接写 AxAx 会把非对称部分错误地保留下来。

常见误区

  • 忘记说明 xxaa 是列向量,导致 aTxa^Tx 的 shape 不清。
  • 把梯度的行列方向与另一套记号约定混用。
  • 只追踪二次型右侧的 xx,漏掉左侧 xTx^T 的贡献。
  • 看到 1/21/2 就认为最终梯度也一定保留 1/21/2
  • 对非对称 AA 仍写 xy=Ax\nabla_x y=Ax
  • 把“AA 对称”误解成 xx 或梯度需要对称。

本课小结

  • 线性型 aTxa^Tx 的列梯度是 aa
  • 二次型中的目标变量同时出现在左、右两个位置。
  • 对称矩阵下,成对交叉项合并并得到 x12xTAx=Ax\nabla_x\frac12x^TAx=Ax
  • 一般矩阵下,正确结果是 12(A+AT)x\frac12(A+A^T)x
  • 逐元素法给出路径直觉,微分法提供更紧凑的复核。
07

主题讲解 · 02:54

从加权连边到线性层矩阵乘法

学习目标

  • 把一个输出神经元的加权和写成向量内积。
  • 把一批样本、多个输出神经元打包成矩阵乘法。
  • 对齐 PyTorch 中 WW、in_features 与 out_features 的轴。
  • 区分仿射变换、偏置广播与激活函数。

前置与衔接

全连接层常画成许多输入节点、输出节点和连边。

矩阵写法则是:

Y=XWT+b.Y=XW^T+b.

两种图不是两种算法。

它们对同一组加权和采用不同的组织方式。

本课沿用 PyTorch 布局:

  • XRN×IX\in\mathbb{R}^{N\times I}
  • WRO×IW\in\mathbb{R}^{O\times I}
  • bROb\in\mathbb{R}^{O}
  • YRN×OY\in\mathbb{R}^{N\times O}

NN 是样本数, II 是输入特征数, OO 是输出特征数。

核心讲解

1. PyTorch 线性层的矩阵布局

PyTorch 把一个输出神经元的全部输入权重存成 WW 的一行。

所以 W.shape=(O,I)W.shape=(O,I)

前向时使用:

Y=XWT+b.Y=XW^T+b.

shape 为:

(N×I)(I×O)=N×O.(N\times I)(I\times O)=N\times O.
图 1

PyTorch 线性层采用 Y=XWT+bY=XW^T+b:输入矩阵的每一行是一条样本,权重矩阵每一行对应一个输出神经元。

原视频 · 00:20 ↗

这里的转置是存储布局带来的。

若另一套教材直接把权重存为 (I,O)(I,O), 就会写 Y=XW~+bY=X\widetilde W+b

2. X 的行是样本,列是特征

二维输入可以写为:

X=[x11x12x1Ix21x22x2I].X= \begin{bmatrix} x_{11}&x_{12}&\cdots&x_{1I}\\ x_{21}&x_{22}&\cdots&x_{2I}\\ \vdots&\vdots&&\vdots \end{bmatrix}.

ii 行:

xi=[xi1xiI]x_i= \begin{bmatrix} x_{i1}&\cdots&x_{iI} \end{bmatrix}

表示第 ii 个样本。

kk 列表示所有样本的第 kk 个特征。

图 2

XX 的行轴枚举样本,列轴枚举输入特征;增加样本只增加行,不改变共享权重。

原视频 · 00:40 ↗

例如在表格数据中, 一行可以是一朵花, 不同列是花瓣长度等特征。

增加样本只增加 XX 的行数。

线性层权重 WW 不随样本改变。

3. 一个输出元素就是一次行列内积

输出第 ii 行第 jj 列为:

yij=k=1IxikWjk+bj.y_{ij} = \sum_{k=1}^{I} x_{ik}W_{jk} + b_j.

忽略偏置时, 它是:

  • XX 的第 ii 行;
  • WTW^T 的第 jj 列;
  • 做一次长度为 II 的内积。
图 3

XX 的每个样本行分别与 WTW^T 的每个输出列做内积,组合成输出矩阵中的全部元素。

原视频 · 01:20 ↗

所有 i,ji,j 组合一起计算, 就是矩阵乘法 XWTXW^T

矩阵乘法不是新的神经元规则。

它只是批量计算全部加权和。

4. 连边图中的权重就是矩阵元素

对固定输出神经元 jj

yj=Wj1x1+Wj2x2++WjIxI+bj.y_j = W_{j1}x_1 + W_{j2}x_2 + \cdots + W_{jI}x_I + b_j.

从输入神经元 kk 连到输出神经元 jj 的边权是 WjkW_{jk}

图 4

一个输出神经元的加权和系数就是连向它的边权;这些系数组成 WW 的对应行。

原视频 · 01:40 ↗

因此:

  • WW 的第 jj 行收集所有指向输出神经元 jj 的边。
  • WW 的第 kk 列收集来自输入特征 kk 的所有出边。

图结构的加权求和与矩阵的一行内积完全一致。

5. 多个样本复用同一套连边

对另一条样本 xix_{i'}

yij=kxikWjk+bj.y_{i'j} = \sum_k x_{i'k}W_{jk}+b_j.

下标 ii' 变了, 但 WjkW_{jk} 没变。

这表示:

  • 不同样本独立计算各自激活。
  • 同一层参数在 batch 内共享。
  • 矩阵乘法可把这些独立样本行同时处理。

训练中对 WW 的梯度需要跨样本累加, 正是因为同一个 WjkW_{jk} 被多行复用。

6. in_features 与 out_features

in_features 是 II

它同时等于:

  • 输入向量最后一维的长度。
  • 输入神经元数量。
  • WW 的列数。
  • WTW^T 的行数。

out_features 是 OO

它同时等于:

  • 输出向量最后一维的长度。
  • 输出神经元数量。
  • WW 的行数。
  • WTW^T 的列数。
图 5

in_features 等于输入神经元数、WW 的列数;out_features 等于输出神经元数、WW 的行数。

原视频 · 02:20 ↗

这个对照表比记“谁在前谁在后”更可靠。

只要检查 W.shape=(O,I)W.shape=(O,I), 其余含义会自动对齐。

7. 偏置是输出特征上的逐分量平移

bjb_j 只属于第 jj 个输出特征。

对每个样本行, 都加同一份 bb

yij=zij+bj,Z=XWT.y_{ij}=z_{ij}+b_j, \qquad Z=XW^T.

因此 bb 沿样本轴广播。

在连边图上, 可把它理解为每个输出神经元额外加一个固定常数。

8. 激活函数在仿射变换之后

严格地说, XWT+bXW^T+b 是仿射变换。

若再接激活函数 ϕ\phi

H=ϕ(XWT+b).H=\phi(XW^T+b).
图 6

偏置向量按输出特征广播到各样本,随后激活函数逐元素作用于仿射变换结果。

原视频 · 02:40 ↗

矩阵乘法负责混合输入特征。

偏置负责逐输出特征平移。

激活函数负责引入非线性。

三者职责不同, 不应都笼统叫“矩阵乘法层”。

9. PyTorch 的额外前导维边界

二维样本矩阵最容易画。

但 PyTorch 线性层可接受:

X.shape=(,I),X.shape=(*,I),

并输出:

Y.shape=(,O).Y.shape=(*,O).

星号代表任意前导维, 例如 batch 与 sequence。

线性层只把最后一维 II 映射为 OO, 其他前导位置独立复用同一权重。

因此“每一行是样本”是一种二维直觉。

在序列模型中, 每个 batch-token 位置都可视为一个独立的特征向量。

跟练与练习

原视频练习

编者练习

设 PyTorch 线性层满足: X.shape=(4,6),W.shape=(3,6),b.shape=(3).X.shape=(4,6), \quad W.shape=(3,6), \quad b.shape=(3). 请写出 Y.shapeY.shape, 展开 y2,1y_{2,1}, 并指出它在连接图中使用哪些边。

查看参考答案

前向:
Y=XWT+b.Y=XW^T+b.
shape 为:
(4,6)(6,3)(4,3).(4,6)(6,3)\rightarrow(4,3).
所以:
Y.shape=(4,3).Y.shape=(4,3).
目标元素:
y2,1=k=16X2kW1k+b1.y_{2,1} = \sum_{k=1}^{6}X_{2k}W_{1k}+b_1.
它使用第 2 个样本的六个输入激活,
以及所有从六个输入神经元指向第 1 个输出神经元的边权。

常见误区

  • XX 的行当特征、列当样本。
  • 忘记 PyTorch 存储的 WW(O,I)(O,I)
  • WTW^T 的列误当成一套新的参数。
  • 认为 batch 中每个样本拥有不同的线性层权重。
  • 把 bias 当成连接所有输入的另一组权重。
  • 把仿射变换本身称为非线性激活。
  • 在三维输入中把每一行机械解释成完整样本,忽略线性层只作用最后一维。

本课小结

  • 一个输出神经元完成一次输入向量与权重向量的内积。
  • 全部样本与全部输出的加权和可打包成 Y=XWT+bY=XW^T+b
  • PyTorch 中 W.shape=(out_features,in_features)W.shape=(\text{out\_features},\text{in\_features})
  • 偏置沿前导位置广播,激活函数在仿射变换之后。
  • 连接图与矩阵乘法是同一运算的两种表达。
08

主题讲解 · 02:35

把标量运算升级为注意力与批量矩阵乘法

学习目标

  • 用“替换运算槽位”的视角理解矩阵乘法。
  • 从外积网格推到 QKTQK^T 的注意力分数矩阵。
  • 区分逐元素乘、矩阵乘与 batch 矩阵乘。
  • 说明多头与多样本轴为什么不会被矩阵乘法混合。

前置与衔接

本课使用一个教学类比:

先观察标量或向量运算的槽位, 再把槽位里的对象升级为向量或矩阵。

这个类比能帮助识别 shape, 但它不是矩阵乘法的形式定义。

真正判断运算是否合法时, 仍要检查:

  • 哪两个轴发生收缩。
  • 哪些轴被保留。
  • 哪些前导轴只做 batch 广播。

下文约定:

  • TT 表示 token 数。
  • dd 表示单头特征维。
  • HH 表示注意力头数。
  • BB 表示 batch 大小。

核心讲解

1. 从标量广播看“运算模板”

标量乘向量:

2[45]=[810].2 \begin{bmatrix} 4&5 \end{bmatrix} = \begin{bmatrix} 8&10 \end{bmatrix}.

这里可以把标量 22 看作复用到每个元素位置。

图 1

标量乘向量可看成同一标量作用于每个位置;视频以“替换槽位对象”作为理解高阶运算的起点。

原视频 · 00:20 ↗

如果只看结构, 这是一个“相同左操作数作用到多个槽位”的模板。

后面把标量换成矩阵时, 也会出现同一个投影矩阵作用于多个样本或 token 的情形。

但要注意:

标量广播没有收缩轴, 矩阵乘法通常有。

二者只是复用结构相似, 计算规则并不相同。

2. 把标量系数换成向量内积

一个神经元的加权和为:

y=wTx=k=1dwkxk.y=w^Tx = \sum_{k=1}^{d}w_kx_k.

原来一个槽位里只有标量相乘。

现在把一组标量乘加打包成两个向量的内积。

图 2

把标量槽位替换成输入向量和权重向量后,每个输出位置由一次向量内积得到,对应一个神经元的加权和。

原视频 · 00:40 ↗

若有多个输出神经元, 每个输出都有一个权重向量。

把这些权重向量叠成矩阵, 就得到一组并行内积:

y=Wx.y=Wx.

所以矩阵乘法可以看作:

在一个规则网格上, 一次计算许多向量内积。

3. 从外积网格到注意力分数矩阵

两个向量做外积时:

aRM,bRN,a\in\mathbb{R}^{M}, \qquad b\in\mathbb{R}^{N},
abTRM×N,(abT)ij=aibj.ab^T\in\mathbb{R}^{M\times N}, \qquad (ab^T)_{ij}=a_i b_j.

输出的每个网格位置对应一对输入槽位。

现在把每个标量槽位升级成 dd 维向量:

qiRd,kjRd.q_i\in\mathbb{R}^{d}, \qquad k_j\in\mathbb{R}^{d}.

再把原来的标量乘积替换成向量内积:

Sij=qiTkj.S_{ij}=q_i^Tk_j.

把所有 query 和 key 按行堆叠:

QRM×d,KRN×d.Q\in\mathbb{R}^{M\times d}, \qquad K\in\mathbb{R}^{N\times d}.

则:

S=QKTRM×N.S=QK^T\in\mathbb{R}^{M\times N}.
图 3

外积的每个标量乘法槽位可替换为 qiq_ikjk_j 的内积,得到注意力分数矩阵 QKTQK^T

原视频 · 01:00 ↗

dd 是收缩轴。

M,NM,N 被保留, 因此输出仍是 query-key 配对网格。

完整注意力还会加入:

  • 1/d1/\sqrt d 缩放。
  • 可选 mask。
  • softmax。
  • 与 value 的乘法。

本课只聚焦 QKTQK^T 这一步。

4. 把逐元素槽位升级为独立矩阵乘

逐元素乘法要求相同位置配对:

ci=aibi.c_i=a_i b_i.

若把每个 ai,bia_i,b_i 换成一对矩阵, 并把位置内的标量乘换成矩阵乘, 就得到一组彼此独立的矩阵乘:

Ci=AiBi.C_i=A_iB_i.
图 4

逐元素乘法的独立槽位若改放矩阵,每个槽位可执行一次互不混合的矩阵乘法。

原视频 · 01:20 ↗

关键不是“矩阵里又装矩阵”。

实际张量会增加一个前导 batch 轴:

ARG×M×K,BRG×K×N,A\in\mathbb{R}^{G\times M\times K}, \qquad B\in\mathbb{R}^{G\times K\times N},
CRG×M×N.C\in\mathbb{R}^{G\times M\times N}.

对每个 gg

Cg=AgBg.C_g=A_gB_g.

GG 轴不参与求和。

只有内部的 KK 轴被收缩。

5. 多头注意力是按头独立的 batch 矩阵乘

忽略样本轴时, 多头 query 和 key 可写为:

Q,KRH×T×d.Q,K\in\mathbb{R}^{H\times T\times d}.

对第 hh 个头:

Sh=QhKhTRT×T.S_h=Q_hK_h^T \in\mathbb{R}^{T\times T}.

合起来:

SRH×T×T.S\in\mathbb{R}^{H\times T\times T}.
图 5

多头注意力把 head 视作 batch 维,各 head 的 QhKhTQ_hK_h^T 独立计算,可由 BMM 并行打包。

原视频 · 01:40 ↗

shape 账本是:

(H,T,d)×(H,d,T)(H,T,T).(H,T,d)\times(H,d,T) \longrightarrow (H,T,T).

dd 被收缩, HH 被保留。

因此不同头之间不会互相点积。

如果错误地把 HH 并进收缩轴, 就会改变多头注意力的语义。

6. 同一个投影矩阵在 batch 中复用

设输入:

XRB×T×D.X\in\mathbb{R}^{B\times T\times D}.

把投影权重写成数学布局:

WQRD×d.W_Q\in\mathbb{R}^{D\times d}.

则:

Q=XWQRB×T×d.Q=XW_Q \in\mathbb{R}^{B\times T\times d}.
图 6

多个样本或用户的输入矩阵共享同一投影权重 WQW_Q,矩阵乘法在 batch 维广播并分别产生各自的 QQ

原视频 · 02:20 ↗

矩阵乘只作用于最后两维。

BB 轴是 batch 轴, 不会被收缩。

同一个 WQW_Q 被每个样本复用。

若按 PyTorch Linear 的存储布局, 权重通常写作:

WQ(pt)Rd×D,W_Q^{(\mathrm{pt})}\in\mathbb{R}^{d\times D},

前向为:

Q=X(WQ(pt))T.Q=X\left(W_Q^{(\mathrm{pt})}\right)^T.

这和 XWQXW_Q 是同一映射的两种权重布局。

7. matmul、bmm 与广播边界

在 PyTorch 中:

  • bmm 接收两个三维张量,batch 大小必须一致。
  • matmul 允许更多前导 batch 维,并按广播规则对齐。
  • 二维乘二维是普通矩阵乘。
  • 星号是逐元素乘,不等于矩阵乘。

例如:

(B,H,T,d)×(B,H,d,T)(B,H,T,T)(B,H,T,d)\times(B,H,d,T) \longrightarrow (B,H,T,T)

表示每个样本、每个头各自做一次矩阵乘。

只有 dd 轴发生求和。

不能因为 shape 中出现 B,HB,H, 就认为这些轴也被网络连接混合。

跟练与练习

跟练:写出多头注意力分数的 shape

设:

H=8,T=128,d=64.H=8, \qquad T=128, \qquad d=64.

则:

Q,KR8×128×64.Q,K\in\mathbb{R}^{8\times128\times64}.

先转置 KK 的最后两维:

KTR8×64×128.K^T\in\mathbb{R}^{8\times64\times128}.

最后两维执行矩阵乘:

S=QKTR8×128×128.S=QK^T \in\mathbb{R}^{8\times128\times128}.

其中:

  • 64 维特征轴被收缩。
  • 8 个头被保留。
  • 两个 128 分别对应 query 与 key 位置。
编者练习

输入 XX 的 shape 为 (B,T,D)=(4,32,512)(B,T,D)=(4,32,512)。 使用 8 个头, 每头 d=64d=64。 回答:

  1. 合并全部头的查询投影输出应是什么 shape?
  2. 拆分头后 QQ 应是什么 shape?
  3. 注意力分数 SS 应是什么 shape?
  4. 哪个轴在 QKTQK^T 中被收缩?
查看参考答案

合并头时,
总查询维数是 8×64=5128\times64=512
所以输出为 (4,32,512)(4,32,512)
拆分头并调整轴顺序后,
QQ(4,8,32,64)(4,8,32,64)
KK 同 shape,
其最后两维转置后为 (4,8,64,32)(4,8,64,32)
因此:
SR4×8×32×32.S\in\mathbb{R}^{4\times8\times32\times32}.
被收缩的是每头的 64 维特征轴。
B=4B=4H=8H=8 都作为独立 batch 轴保留。

常见误区

误区 1:类比本身就是严格定义

“把标量换成向量或矩阵”是认知脚手架。

严格结果必须由索引式和 shape 得出。

误区 2:外积和点积是一回事

向量外积保留两条索引轴。

向量点积收缩特征轴并输出标量。

QKTQK^T 是许多 query-key 点积组成的二维网格。

误区 3:batch 矩阵乘会混合不同 batch

batch 轴只索引多组独立乘法。

矩阵乘本身发生在最后两维。

误区 4:多头轴也参与点积

标准多头注意力中, 每个头独立计算 QhKhTQ_hK_h^T

头轴被保留, 不会被求和。

误区 5:PyTorch 权重总写成输入维乘输出维

PyTorch Linear 参数存成 (O,I)(O,I)

数学推导常把同一线性映射写成 (I,O)(I,O)

比较公式前必须先对齐布局。

本课小结

矩阵乘法可以从“批量向量内积”理解。

注意力分数 QKTQK^T 把 query-key 配对网格中的每个槽位变成向量内积。

batch 矩阵乘则把多组矩阵乘放到前导轴上独立执行。

最稳妥的检查方法始终是:

  1. 找到收缩轴。
  2. 写出保留轴。
  3. 标出只负责索引独立任务的 batch 轴。
  4. 对齐数学布局与框架存储布局。

这样就能从标量类比走向严格的张量语义。

09

主题讲解 · 03:26

用乘积规则统一推导矩阵反向传播

学习目标

  • 从标量乘积的链式法则推广到矩阵乘积。
  • 推导 Y=ABCY=ABC 对三个因子的反向传播公式。
  • 用 shape 检查矩阵梯度的乘法顺序。
  • 对齐 PyTorch 中 Y=XWTY=XW^TdXdXdWdW

前置与衔接

本课讨论标量损失 LL 经矩阵 YY 继续反传。

记上游梯度为 G=YLG=\nabla_YL,它与 YY 同 shape。

矩阵之间没有无歧义的“除法”,所以用微分和 Frobenius 内积定义梯度:

dL=G,dYF=tr(GTdY).dL=\langle G,dY\rangle_F=\operatorname{tr}(G^TdY).

若目标变量是 AA,就把含 dAdA 的部分整理为:

dL=tr((AL)TdA).dL=\operatorname{tr}\left((\nabla_A L)^TdA\right).

由此读出 AL\nabla_A L

核心讲解

1. 标量乘积给出位置模板

若:

y=abc,g=Ly,y=abc,\qquad g=\frac{\partial L}{\partial y},

则:

La=gbc,\frac{\partial L}{\partial a}=g\,bc,
Lb=agc,\frac{\partial L}{\partial b}=a\,g\,c,
Lc=abg.\frac{\partial L}{\partial c}=ab\,g.
图 1

对标量乘积 y=abcy=abc,可把上游梯度放在被求导因子的原位置;标量交换律暂时掩盖了顺序问题。

原视频 · 00:20 ↗

可以把它理解为:

目标因子的位置由上游梯度接管,其他因子仍位于目标两侧。

标量乘法可交换,矩阵乘法不可交换。

推广后不能随意移动因子,转置也必须服从顺序反转规则。

2. 先建立 shape 账本

设:

ARm×n,BRn×p,CRp×q,A\in\mathbb{R}^{m\times n},\quad B\in\mathbb{R}^{n\times p},\quad C\in\mathbb{R}^{p\times q},
Y=ABCRm×q,GRm×q.Y=ABC\in\mathbb{R}^{m\times q},\qquad G\in\mathbb{R}^{m\times q}.

三个梯度必须分别满足:

AL:(m,n),BL:(n,p),CL:(p,q).\nabla_A L:(m,n),\qquad \nabla_B L:(n,p),\qquad \nabla_C L:(p,q).

“梯度与变量同 shape”是最直接的公式单元测试。

3. 对三个因子使用乘积微分

Y=ABCY=ABC

dY=(dA)BC+A(dB)C+AB(dC).dY=(dA)BC+A(dB)C+AB(dC).

每一项只含一个目标变量的微分。

把它代入 dL=tr(GTdY)dL=\operatorname{tr}(G^TdY),就能逐项读出梯度。

图 2

Y=ABCY=ABC,梯度分别为 dA=dY(BC)TdA=dY(BC)^TdB=ATdYCTdB=A^TdYC^TdC=(AB)TdYdC=(AB)^TdY

原视频 · 01:00 ↗

4. 对 A 求梯度

只看 dAdA 项:

dLA=tr(GT(dA)BC).dL_A=\operatorname{tr}\left(G^T(dA)BC\right).

利用迹的循环移位:

dLA=tr(BCGTdA).dL_A=\operatorname{tr}\left(BCG^TdA\right).

tr((AL)TdA)\operatorname{tr}\left((\nabla_A L)^TdA\right) 对照:

AL=G(BC)T=GCTBT.\nabla_A L=G(BC)^T=GC^TB^T.

shape 检查:

(m,q)(q,p)(p,n)=(m,n).(m,q)(q,p)(p,n)=(m,n).

结果与 AA 同 shape。

5. 转置乘积会反转顺序

必须使用:

(BC)T=CTBT.(BC)^T=C^TB^T.

不能写成 BTCTB^TC^T

图 3

被求导矩阵右侧的乘积必须整体转置;例如 (BC)T=CTBT(BC)^T=C^TB^T,不能保持原顺序。

原视频 · 01:20 ↗

标量公式中位于目标右侧的 BCBC,在矩阵反传中变成整体转置 (BC)T(BC)^T

这也是计算图反向传播时顺序反转的具体表现。

6. 对 B 与 C 求梯度

BB 的微分项:

dLB=tr(GTA(dB)C).dL_B=\operatorname{tr}\left(G^TA(dB)C\right).

整理后得到:

BL=ATGCT.\nabla_B L=A^TGC^T.

shape 为:

(n,m)(m,q)(q,p)=(n,p).(n,m)(m,q)(q,p)=(n,p).

CC

dLC=tr(GTAB(dC)),dL_C=\operatorname{tr}\left(G^TAB(dC)\right),

所以:

CL=(AB)TG=BTATG.\nabla_C L=(AB)^TG=B^TA^TG.

shape 为:

(p,n)(n,m)(m,q)=(p,q).(p,n)(n,m)(m,q)=(p,q).
图 4

权重位于输入右侧、左侧或带显式转置时,梯度乘法顺序不同;必须从实际前向布局推导。

原视频 · 02:00 ↗

三条结论汇总为:

AL=GCTBT,\boxed{\nabla_A L=GC^TB^T},
BL=ATGCT,\boxed{\nabla_B L=A^TGC^T},
CL=BTATG.\boxed{\nabla_C L=B^TA^TG}.

7. 口诀只能在 shape 复核下使用

可以把目标因子替换成上游梯度:

  • 目标左边的因子转置后仍放在左边。
  • 目标右边的乘积整体转置后放在右边。
  • 转置一个乘积时,内部顺序反转。

例如目标是 BB

Y=ABC,Y=\underbrace{A}_{左}B\underbrace{C}_{右},

所以:

BL=ATGCT.\nabla_B L=A^TGC^T.

这个口诀只是微分推导的压缩版本。

有广播、重复使用、逐元素乘或非标量损失时,必须回到具体计算图。

8. PyTorch Linear 的权重布局

PyTorch Linear 使用:

XRN×I,WRO×I,X\in\mathbb{R}^{N\times I},\quad W\in\mathbb{R}^{O\times I},
Y=XWTRN×O.Y=XW^T\in\mathbb{R}^{N\times O}.

上游梯度 GG 的 shape 为 (N,O)(N,O)

对输入:

XL=GW.\nabla_X L=GW.

shape:

(N,O)(O,I)=(N,I).(N,O)(O,I)=(N,I).
图 5

PyTorch 约定 Y=XWTY=XW^T,因此 dX=dYWdX=dYW,而 dW=dYTXdW=dY^TX

原视频 · 02:40 ↗

对权重可先令 V=WTV=W^T

因为 Y=XVY=XV,所以:

VL=XTG.\nabla_VL=X^TG.

再转回实际存储的 WW

WL=(VL)T=GTX.\nabla_WL=(\nabla_VL)^T=G^TX.

shape:

(O,N)(N,I)=(O,I).(O,N)(N,I)=(O,I).

它与参数 WW 完全一致。

9. 布局改变,梯度公式也改变

若前向改为 Y=XWY=XW

XL=GWT,WL=XTG.\nabla_XL=GW^T,\qquad \nabla_WL=X^TG.

若前向改为 Y=WXY=WX

XL=WTG,WL=GXT.\nabla_XL=W^TG,\qquad \nabla_WL=GX^T.

LoRA 分支若写成:

Y=XAB,Y=XAB,

则:

AL=XTGBT,\nabla_A L=X^TGB^T,
BL=(XA)TG=ATXTG.\nabla_B L=(XA)^TG=A^TX^TG.
图 6

Y=XWY=XWY=WXY=WXY=XABY=XAB 等布局都能用同一规则推导,LoRA 的低秩双因子只是更长乘积的实例。

原视频 · 03:00 ↗

不存在脱离前向表达式的固定反传口诀。

先写布局,再推梯度。

10. 框架实际计算的是 VJP

反向传播已知上游梯度 GG,再求每个输入的梯度。

这一步是 vector-Jacobian product,简称 VJP。

矩阵乘法算子不需要显式构造巨大 Jacobian。

框架直接调用上述矩阵乘公式,得到与各输入同 shape 的结果。

跟练与练习

跟练:检查 Y=ABCY=ABC 对 B 的梯度

设:

A:(2,3),B:(3,4),C:(4,5),G:(2,5).A:(2,3),\quad B:(3,4),\quad C:(4,5),\quad G:(2,5).

候选公式:

BL=ATGCT.\nabla_B L=A^TGC^T.

逐步检查:

ATG:(3,2)(2,5)(3,5),A^TG:(3,2)(2,5)\rightarrow(3,5),
(ATG)CT:(3,5)(5,4)(3,4).(A^TG)C^T:(3,5)(5,4)\rightarrow(3,4).

结果与 B:(3,4)B:(3,4) 相同。

编者练习

Y=XWTY=XW^T,其中: X:(32,768),W:(3072,768),G:(32,3072).X:(32,768),\qquad W:(3072,768),\qquad G:(32,3072). 请写出:

  1. XL\nabla_XL 的公式与 shape。
  2. WL\nabla_WL 的公式与 shape。
  3. 为什么不能把 WL\nabla_WL 写成 XTGX^TG 后直接结束?
查看参考答案

对输入:
XL=GW:(32,3072)(3072,768)(32,768).\nabla_XL=GW:(32,3072)(3072,768)\rightarrow(32,768).
对权重:
WL=GTX:(3072,32)(32,768)(3072,768).\nabla_WL=G^TX:(3072,32)(32,768)\rightarrow(3072,768).
XTGX^TG 的 shape 是 (768,3072)(768,3072)
它对应前向中 WTW^T 这一中间矩阵的梯度,不是 PyTorch 实际参数 W:(3072,768)W:(3072,768) 的梯度。
还需转置一次,才得到 GTXG^TX

常见误区

误区 1:矩阵因子可以像标量一样换序

一般 ABBAAB\neq BA

反传顺序由前向图和转置规则决定。

误区 2:(BC)T=BTCT(BC)^T=B^TC^T

正确公式是 (BC)T=CTBT(BC)^T=C^TB^T

误区 3:任何线性层都背 dX=dYWdX=dYW

它只对应 Y=XWTY=XW^T

前向若是 Y=XWY=XW,就应写 dX=dYWTdX=dYW^T

误区 4:梯度 shape 可以与参数不同

标量损失对参数的梯度必须与参数同 shape。

shape 不同通常表示漏了转置或顺序错误。

误区 5:反传会显式构造完整 Jacobian

常规自动微分为算子实现 VJP。

矩阵乘法只需几次矩阵乘,无需存全部逐元素偏导。

本课小结

矩阵反向传播的可靠流程是:

  1. 写前向布局与 shape。
  2. 用乘积微分展开目标变量。
  3. 用 Frobenius 内积和迹移位读梯度。
  4. 转置乘积时反转内部顺序。
  5. 用梯度与变量同 shape 复核。

Y=ABCY=ABC

AL=GCTBT,BL=ATGCT,CL=BTATG.\nabla_A L=GC^TB^T,\quad \nabla_B L=A^TGC^T,\quad \nabla_C L=B^TA^TG.

对 PyTorch 的 Y=XWTY=XW^T

XL=GW,WL=GTX.\nabla_XL=GW,\qquad \nabla_WL=G^TX.

这些公式都是局部 Jacobian 与上游梯度相乘后的 VJP 结果。

10

主题讲解 · 03:19

从梯度到高阶 Jacobian 的统一定义

学习目标

  • 区分标量对张量求导与张量对张量求导。
  • 用索引定义向量 Jacobian 和矩阵 Jacobian。
  • 判断 Jacobian 的阶数、shape 与元素数量。
  • 对齐行梯度约定和列梯度约定下的链式法则。

前置与衔接

“求导结果是什么 shape”取决于两个问题:

  1. 输出有多少个自由分量?
  2. 输入有多少个自由分量?

标量输出只有一个分量。

所以标量对张量求导时,结果可以直接沿用输入的 shape。

张量输出有多个分量。

若要保存每个输出分量对每个输入分量的偏导,就必须同时保留输出轴和输入轴。

本课把这种完整导数称为广义 Jacobian。

核心讲解

1. 标量对张量求导仍与输入同 shape

设标量:

LR.L\in\mathbb{R}.

若输入是向量:

xRn,x\in\mathbb{R}^{n},

梯度包含:

Lxi,i=1,,n.\frac{\partial L}{\partial x_i},\qquad i=1,\ldots,n.

它可以排列成与 xx 同 shape 的向量。

图 1

标量损失对张量求导时,对每个输入元素求偏导并按原位置排列,因此梯度与输入张量同形。

原视频 · 00:20 ↗

若输入是矩阵 XRa×bX\in\mathbb{R}^{a\times b}

(XL)ij=LXij.(\nabla_XL)_{ij}=\frac{\partial L}{\partial X_{ij}}.

所以:

XLRa×b.\nabla_XL\in\mathbb{R}^{a\times b}.

三维输入同理。

输出标量没有额外输出轴,因此梯度只需保留输入轴。

2. 张量对张量求导需要完整 Jacobian

设:

Y=f(X).Y=f(X).

如果 YYXX 都有多个元素,完整导数必须回答:

每个 Y 元素对每个 X 元素的偏导是多少?\text{每个 }Y\text{ 元素对每个 }X\text{ 元素的偏导是多少?}

因此它包含一个输出索引组和一个输入索引组。

图 2

张量 YY 对张量 XX 求导,要记录每个 YY 元素对每个 XX 元素的偏导,得到广义 Jacobian。

原视频 · 01:00 ↗

若:

Y.shape=(s1,,sr),Y.shape=(s_1,\ldots,s_r),
X.shape=(t1,,tk),X.shape=(t_1,\ldots,t_k),

按本课采用的“输出轴在前、输入轴在后”约定:

J.shape=(s1,,sr,t1,,tk).J.shape=(s_1,\ldots,s_r,t_1,\ldots,t_k).

3. Jacobian 的阶数与元素数量

YYrr 阶张量,XXkk 阶张量,则完整 Jacobian 是:

r+k 阶张量.r+k\text{ 阶张量}.

它的元素数为:

#J=(#Y)(#X).\#J=(\#Y)(\#X).
图 3

YYrYr_Y 阶、XXrXr_X 阶,未展平 Jacobian 的阶数为 rY+rXr_Y+r_X,元素数为 #Y×#X\#Y\times\#X

原视频 · 01:20 ↗

例如:

Y:(2,3),X:(4,5),Y:(2,3),\qquad X:(4,5),

则:

J:(2,3,4,5),J:(2,3,4,5),

元素数:

2×3×4×5=120.2\times3\times4\times5=120.

这里“阶数”指张量轴数,不是矩阵的 rank。

二者不要混淆。

4. 向量 Jacobian 的索引定义

设行向量:

xR1×n,yR1×m.x\in\mathbb{R}^{1\times n},\qquad y\in\mathbb{R}^{1\times m}.

定义:

Jij=yixj.J_{ij}=\frac{\partial y_i}{\partial x_j}.

因此:

JRm×n.J\in\mathbb{R}^{m\times n}.

第一条轴枚举输出分量。

第二条轴枚举输入分量。

这个顺序与 J.shape=(Y.shape,X.shape)J.shape=(Y.shape,X.shape) 的推广一致。

5. 视频采用行梯度约定

视频把上游梯度写成行向量:

gy=[Ly1Lym].g_y= \begin{bmatrix} \frac{\partial L}{\partial y_1}&\cdots& \frac{\partial L}{\partial y_m} \end{bmatrix}.

则输入梯度为:

gx=gyJ.g_x=g_yJ.

shape:

(1,m)(m,n)=(1,n).(1,m)(m,n)=(1,n).
图 4

在视频的行梯度约定下,向量链式法则写成 L/X=(L/Y)(Y/X)\partial L/\partial X=(\partial L/\partial Y)(\partial Y/\partial X)

原视频 · 02:00 ↗

jj 个分量是:

(gx)j=i=1mLyiyixj.(g_x)_j= \sum_{i=1}^{m} \frac{\partial L}{\partial y_i} \frac{\partial y_i}{\partial x_j}.

这正是标量多路径链式法则。

图 5

行向量上游梯度乘 YYXX 的 Jacobian,输出仍是与 XX 同形的行梯度。

原视频 · 02:20 ↗

6. 列梯度约定写成 JTgyJ^Tg_y

许多教材把 x,yx,y 和梯度都写成列向量。

若仍定义:

Jij=yixj,J_{ij}=\frac{\partial y_i}{\partial x_j},

则:

gyRm×1,g_y\in\mathbb{R}^{m\times1},
gx=JTgyRn×1.g_x=J^Tg_y\in\mathbb{R}^{n\times1}.

展开仍是:

(gx)j=iyixjLyi.(g_x)_j= \sum_i \frac{\partial y_i}{\partial x_j} \frac{\partial L}{\partial y_i}.

所以:

  • 行梯度约定:gx=gyJg_x=g_yJ
  • 列梯度约定:gx=JTgyg_x=J^Tg_y

两者只是排列方向不同,偏导内容完全相同。

比较公式前必须先确认梯度是行还是列。

7. 矩阵对矩阵的 Jacobian 有四个索引

设:

YRa×b,XRc×d.Y\in\mathbb{R}^{a\times b},\qquad X\in\mathbb{R}^{c\times d}.

完整 Jacobian 定义为:

Jijkl=YijXkl.J_{ij\,kl}= \frac{\partial Y_{ij}}{\partial X_{kl}}.

其 shape 为:

JRa×b×c×d.J\in\mathbb{R}^{a\times b\times c\times d}.
图 6

矩阵对矩阵求导得到四阶张量,元素 Jijkl=Yij/XklJ_{ij\,kl}=\partial Y_{ij}/\partial X_{kl}

原视频 · 02:40 ↗

i,ji,j 定位输出元素。

k,lk,l 定位输入元素。

若把 YYXX 分别展平,完全相同的信息也可存为:

JflatR(ab)×(cd).J_{\mathrm{flat}}\in\mathbb{R}^{(ab)\times(cd)}.

四阶形式保留原始轴语义。

二维展平形式便于与普通矩阵乘对应。

8. 标量梯度是 Jacobian 的特殊情形

Y=LY=L 是标量时,输出没有非平凡轴。

于是完整 Jacobian 只剩输入轴:

J.shape=X.shape.J.shape=X.shape.

这就是为什么标量损失对参数求导时,梯度天然与参数同 shape。

向量梯度、矩阵梯度和高阶张量梯度并非另一套定义。

它们都是广义 Jacobian 在标量输出情形下的简化。

9. 实际自动微分通常不保存完整 Jacobian

完整 Jacobian 的元素数量是 (#Y)(#X)(\#Y)(\#X)

在神经网络中它可能极其庞大。

反向传播通常只需要:

上游梯度×局部 Jacobian.\text{上游梯度}\times\text{局部 Jacobian}.

也就是 VJP。

框架为每个算子直接实现该乘积,避免显式生成完整 JJ

本课的完整 Jacobian 主要用于建立定义、shape 和索引语义。

跟练与练习

跟练:从索引判断 Jacobian shape

设:

YR2×3,XR4.Y\in\mathbb{R}^{2\times3},\qquad X\in\mathbb{R}^{4}.

定义:

Jijk=YijXk.J_{ij\,k}=\frac{\partial Y_{ij}}{\partial X_k}.

所以:

J.shape=(2,3,4).J.shape=(2,3,4).

阶数为 2+1=32+1=3

元素数为:

2×3×4=24.2\times3\times4=24.
编者练习

设: y1=x12+x2,y2=x1x2.y_1=x_1^2+x_2,\qquad y_2=x_1x_2. 采用: Jij=yixj.J_{ij}=\frac{\partial y_i}{\partial x_j}. 给定行上游梯度: gy=[u1u2].g_y= \begin{bmatrix} u_1&u_2 \end{bmatrix}. 请写出 Jacobian JJ 和行输入梯度 gxg_x

查看参考答案

逐项求偏导:
J=[2x11x2x1].J= \begin{bmatrix} 2x_1&1\\ x_2&x_1 \end{bmatrix}.
行梯度约定下:
gx=gyJ=[u1u2][2x11x2x1].g_x=g_yJ = \begin{bmatrix} u_1&u_2 \end{bmatrix} \begin{bmatrix} 2x_1&1\\ x_2&x_1 \end{bmatrix}.
所以:
gx=[2u1x1+u2x2u1+u2x1].g_x= \begin{bmatrix} 2u_1x_1+u_2x_2& u_1+u_2x_1 \end{bmatrix}.
若改用列梯度,写成 gx=JTgyg_x=J^Tg_y,分量结果相同,只是排列为列向量。

常见误区

误区 1:张量阶数就是矩阵秩

张量阶数是轴数。

矩阵秩是线性无关行或列的数量。

本课的“r+kr+k 阶”指前者。

误区 2:张量对张量求导仍与输入同 shape

只有输出是标量时,梯度才直接与输入同 shape。

多元素输出的完整导数还要保留输出轴。

误区 3:gyJg_yJJTgyJ^Tg_y 相互矛盾

前者使用行梯度,后者使用列梯度。

先统一向量方向,再比较公式。

误区 4:框架必须保存完整 Jacobian

反向传播一般直接计算 VJP。

显式 Jacobian 主要用于分析、小规模验证和高阶导需求。

误区 5:展平会改变偏导值

只要展平索引顺序固定,展平只改变存储布局。

它不会改变每对输出—输入元素之间的偏导。

本课小结

标量对张量的梯度与输入同 shape。

张量 YY 对张量 XX 的完整 Jacobian 同时保留两者的轴:

J.shape=Y.shape+X.shape.J.shape=Y.shape+X.shape.

它的阶数是两者阶数之和,元素数是两者元素数之积。

对向量:

Jij=yixj.J_{ij}=\frac{\partial y_i}{\partial x_j}.

行梯度约定写 gx=gyJg_x=g_yJ

列梯度约定写 gx=JTgyg_x=J^Tg_y

二者表达同一个链式法则。

11

主题讲解 · 03:28

反向传播为何是向量—Jacobian 乘积

学习目标

  • 从多变量链式法则推导向量—Jacobian 乘积。
  • 说明行梯度约定下为什么写成 gx=gyJg_x=g_yJ
  • 把矩阵之间的链式法则写成索引收缩。
  • 区分显式 Jacobian 与自动微分实际执行的 VJP。

前置与衔接

上一课定义:

Jij=yixj.J_{ij}=\frac{\partial y_i}{\partial x_j}.

本课继续采用视频中的行梯度约定:

gy=[L/y1L/ym].g_y= \begin{bmatrix} \partial L/\partial y_1&\cdots&\partial L/\partial y_m \end{bmatrix}.

若使用列梯度,等价公式会写成 gx=JTgyg_x=J^Tg_y

这只是布局约定不同。

本课的核心不是“必须构造 Jacobian”,而是:

反向传播需要计算上游梯度与局部 Jacobian 的乘积。

核心讲解

1. 从一条标量链路开始

若:

Lyx,L\rightarrow y\rightarrow x,

则:

Lx=Lyyx.\frac{\partial L}{\partial x} = \frac{\partial L}{\partial y} \frac{\partial y}{\partial x}.

一个上游梯度乘一个局部导数。

yyxx 都变成向量时,路径数量增加,但规则不变:

每条从 xjx_jyiy_iLL 的路径都贡献一个乘积。

图 1

采用行梯度时,dX=dYJdX=dYJ:上游行向量与 Jacobian 相乘得到输入行梯度。

原视频 · 00:20 ↗

2. Jacobian 把全部局部导数排成矩阵

设:

xR1×n,yR1×m.x\in\mathbb{R}^{1\times n},\qquad y\in\mathbb{R}^{1\times m}.

定义:

J=[y1x1y1xnymx1ymxn].J= \begin{bmatrix} \frac{\partial y_1}{\partial x_1}&\cdots&\frac{\partial y_1}{\partial x_n}\\ \vdots&&\vdots\\ \frac{\partial y_m}{\partial x_1}&\cdots&\frac{\partial y_m}{\partial x_n} \end{bmatrix}.

所以:

JRm×n.J\in\mathbb{R}^{m\times n}.
图 2

Jacobian 的第 ii 行第 jj 列定义为 Jij=Yi/XjJ_{ij}=\partial Y_i/\partial X_j

原视频 · 01:00 ↗

行对应输出分量。

列对应输入分量。

3. 一次矩阵乘汇总所有反向路径

行梯度约定下:

gx=gyJ.g_x=g_yJ.

shape:

(1,m)(m,n)=(1,n).(1,m)(m,n)=(1,n).

jj 个输入梯度为:

(gx)j=i=1mLyiyixj.(g_x)_j = \sum_{i=1}^{m} \frac{\partial L}{\partial y_i} \frac{\partial y_i}{\partial x_j}.
图 3

dXdX 的一个分量等于 i(dY)iYi/Xj\sum_i (dY)_i\,\partial Y_i/\partial X_j,正是标量多元链式法则。

原视频 · 01:20 ↗

这正是标量链式法则对所有中间变量 yiy_i 的求和。

因此 VJP 不是额外发明的规则。

它只是把大量标量路径求和打包成矩阵乘法。

4. 为什么反向顺序与计算图相反

若前向有:

xyzL,x\rightarrow y\rightarrow z\rightarrow L,

则反向从:

zL\nabla_zL

开始,依次计算:

yL=zLJzy,\nabla_yL=\nabla_zL\,J_{z\leftarrow y},
xL=yLJyx.\nabla_xL=\nabla_yL\,J_{y\leftarrow x}.

合起来:

xL=zLJzyJyx.\nabla_xL = \nabla_zL J_{z\leftarrow y} J_{y\leftarrow x}.

局部 Jacobian 按前向图的反方向依次接到右侧。

框架只需保留当前上游梯度并调用每个算子的 backward 规则。

5. 张量可以先展平为普通 Jacobian

设:

YRa×b,XRc×d.Y\in\mathbb{R}^{a\times b},\qquad X\in\mathbb{R}^{c\times d}.

分别展平后:

vec(Y)Rab,\operatorname{vec}(Y)\in\mathbb{R}^{ab},
vec(X)Rcd.\operatorname{vec}(X)\in\mathbb{R}^{cd}.

普通二维 Jacobian 为:

JflatR(ab)×(cd).J_{\mathrm{flat}}\in\mathbb{R}^{(ab)\times(cd)}.

行 VJP 写成:

vec(gX)=vec(gY)Jflat.\operatorname{vec}(g_X) = \operatorname{vec}(g_Y)J_{\mathrm{flat}}.

只要展平顺序固定,偏导关系不会改变。

但展平会隐藏矩阵原有的行列轴语义。

6. 保留张量轴时,链式法则变成收缩

保留原 shape,定义四阶 Jacobian:

Jijkl=YijXkl.J_{ij\,kl} = \frac{\partial Y_{ij}}{\partial X_{kl}}.

其中:

J.shape=(a,b,c,d).J.shape=(a,b,c,d).
图 4

输入输出为高阶张量时,反向仍是上游梯度与 Jacobian 的广义乘法,即对输出轴做张量收缩。

原视频 · 02:00 ↗
图 5

矩阵 YY 对矩阵 XX 的 Jacobian 是四阶张量,前两轴标记输出,后两轴标记输入。

原视频 · 02:20 ↗

上游梯度:

gYRa×b.g_Y\in\mathbb{R}^{a\times b}.

目标是:

gXRc×d.g_X\in\mathbb{R}^{c\times d}.

必须把共同的输出索引 i,ji,j 求和掉。

7. 矩阵反向传播的索引公式

对每个输入位置 (k,l)(k,l)

(gX)kl=i=1aj=1b(gY)ijJijkl.(g_X)_{kl} = \sum_{i=1}^{a} \sum_{j=1}^{b} (g_Y)_{ij} J_{ij\,kl}.

这就是张量 contraction。

图 6

dXkl=ijdYijJijkldX_{kl}=\sum_{ij}dY_{ij}J_{ij\,kl},对共享输出索引 i,ji,j 乘加求和后留下输入索引 k,lk,l

原视频 · 02:40 ↗

shape 变化为:

(a,b)    (a,b,c,d)a,b 收缩(c,d).(a,b) \;\text{与}\; (a,b,c,d) \quad \overset{a,b\text{ 收缩}}{\longrightarrow} (c,d).

收缩掉的是输出轴。

保留下来的是输入轴。

所以结果自然与 XX 同 shape。

8. einsum 只是显式 Jacobian 下的索引记法

若已经显式得到 JJ,上式可概念性写成:

torch.einsum("ij,ijkl->kl", gY, J)

字母 i,ji,j 同时出现在输入而不出现在输出中,因此被求和。

k,lk,l 出现在输出中,因此被保留。

这行表达很适合验证索引语义。

但它不表示大型网络应该先构造完整 JJ

显式 JJ 的元素数为:

(ab)(cd),(ab)(cd),

常常无法承受。

9. 实际 autograd 直接实现 VJP

以矩阵乘为例:

Y=XW.Y=XW.

完整 Jacobian 很大,但给定上游梯度 GG 后:

XL=GWT,\nabla_XL=GW^T,
WL=XTG.\nabla_WL=X^TG.

框架直接调用这两次矩阵乘。

不需要先保存:

YijXkl\frac{\partial Y_{ij}}{\partial X_{kl}}

的全部组合。

所以“反向传播的本质是乘 Jacobian”应准确理解为:

  • 数学上,结果等于 VJP。
  • 工程上,通常用算子专属 backward 直接计算 VJP。
  • 只有小规模分析或显式请求 Jacobian 时,才真正物化完整 JJ

跟练与练习

跟练:识别 contraction 的轴

设:

gY.shape=(2,3),g_Y.shape=(2,3),
J.shape=(2,3,4,5).J.shape=(2,3,4,5).

目标:

gX.shape=(4,5).g_X.shape=(4,5).

索引式:

(gX)kl=i=12j=13(gY)ijJijkl.(g_X)_{kl} = \sum_{i=1}^{2} \sum_{j=1}^{3} (g_Y)_{ij}J_{ij\,kl}.

共同输出轴 (2,3)(2,3) 被收缩。

输入轴 (4,5)(4,5) 被保留。

编者练习

Y,XR2×2Y,X\in\mathbb{R}^{2\times2},且: Jijkl=YijXkl.J_{ij\,kl} = \frac{\partial Y_{ij}}{\partial X_{kl}}. 回答:

  1. JJ 的 shape 和元素数是多少?
  2. 给定 gYg_Y,如何写出 (gX)12(g_X)_{12}
  3. 若用 einsum,应保留哪两个索引?
查看参考答案

J.shape=(2,2,2,2)J.shape=(2,2,2,2),共有:
24=162^4=16
个元素。
输入位置 (1,2)(1,2) 的梯度为:
(gX)12=i=12j=12(gY)ijJij12.(g_X)_{12} = \sum_{i=1}^{2} \sum_{j=1}^{2} (g_Y)_{ij}J_{ij\,12}.
einsum 的概念写法是:
torch.einsum("ij,ijkl->kl", gY, J)
i,ji,j 被收缩,k,lk,l 被保留。

常见误区

误区 1:反向传播必须显式构造 Jacobian

反向结果等价于 VJP。

自动微分通常直接实现 VJP,而不物化完整 JJ

误区 2:gyJg_yJJTgyJ^Tg_y 只有一个正确

前者是行梯度约定。

后者是列梯度约定。

统一方向后,它们的分量公式相同。

误区 3:张量收缩是与矩阵乘无关的新规则

把张量展平后,收缩就是普通 VJP。

保留张量轴只是让索引语义更清楚。

误区 4:einsum 写法天然高效

einsum 能简洁表达索引关系。

若输入包含显式巨大 Jacobian,内存成本仍然巨大。

误区 5:收缩的是输入轴

反向从 gYg_Y 得到 gXg_X 时,共同的输出轴被求和。

输入轴保留为结果轴。

本课小结

反向传播把标量链式法则的多条路径求和组织成 VJP。

向量情形下:

gx=gyJg_x=g_yJ

是行梯度约定。

矩阵到矩阵的情形下:

(gX)kl=ij(gY)ijJijkl.(g_X)_{kl} = \sum_{ij} (g_Y)_{ij} J_{ij\,kl}.

这一步沿输出索引收缩并保留输入索引。

数学上它等价于乘完整 Jacobian。

工程上,自动微分通常通过局部算子的 backward 规则直接计算 VJP,避免构造巨大 Jacobian。

12

单元综合

从局部导数到 VJP:矩阵反向传播的 shape 驱动方法

单元能力目标

完成本单元后,应能从标量依赖路径出发,推导常见张量算子的反向传播,而不是靠背转置位置。

具体需要做到:

  • 从加权连边写出线性层矩阵形式;
  • 推导 Y=XWT+bY=XW^T+bdXdXdWdWdbdb
  • 用“前向广播、反向归约”恢复任意输入 shape;
  • 推导 ReLU、Sigmoid 与逐元素乘法的局部 backward;
  • 从逐元素法与微分法推导线性型、二次型和矩阵乘积梯度;
  • 区分 batch 轴、保留轴与收缩轴;
  • 说明张量 Jacobian 的 shape;
  • 用 VJP 解释自动微分为何不显式构造巨大 Jacobian。

概念连接

1. 一个神经元先是向量内积

输入

xRIx\in\mathbb R^{I}

与一个输出神经元的权重

wjRIw_j\in\mathbb R^{I}

产生

yj=wjTx+bj.y_j=w_j^Tx+b_j.

每个 wjkw_{jk} 是输入分量 xkx_k 到输出 yjy_j 的加权连边。

全部 OO 个输出可堆叠为

y=Wx+b,y=Wx+b,

其中 PyTorch 常见权重 shape 为

WRO×I.W\in\mathbb R^{O\times I}.

2. 批量线性层统一为矩阵乘法

NN 个样本:

XRN×I,X\in\mathbb R^{N\times I},

前向为

Y=XWT+b,Y=XW^T+b,

其中

YRN×O,bRO.Y\in\mathbb R^{N\times O}, \qquad b\in\mathbb R^{O}.

bb 沿样本轴广播。

数学资料也常把权重写为 I×OI\times O 并使用 XWXW;推导前必须固定约定。

3. 局部 backward 的统一结构

设标量损失为 LL,算子输出为 YY,输入为 XX,上游梯度为 G=L/YG=\partial L/\partial Y

局部反向用链式法则把 GG 与局部 Jacobian 收缩,并把所有从 XXLL 的依赖路径贡献相加。

不同算子的 backward 只是局部 Jacobian 结构不同。

4. 基础逐元素算子的局部 VJP

ReLU 的反向是门控:

dX=G1(X>0),dX=G\odot\mathbf1(X>0),

其中 X=0X=0 处由框架选择子梯度,常见实现取 0。

Sigmoid 可复用前向输出 Y=σ(X)Y=\sigma(X)

dX=GY(1Y).dX=G\odot Y\odot(1-Y).

逐元素乘法 Y=ABY=A\odot B 有两条输入路径:

dA=GB,dB=GA.dA=G\odot B, \qquad dB=G\odot A.

若前向发生广播,局部梯度之后还必须归约回每个输入的原 shape。

7. 从单元素推导线性层输入梯度

Y=XWT,Y=XW^T,

元素形式为

Yij=kXikWjk.Y_{ij} = \sum_kX_{ik}W_{jk}.

固定输入元素 XikX_{ik},它影响同一样本行的全部输出 YijY_{ij}

所以

LXik=jGijWjk.\frac{\partial L}{\partial X_{ik}} = \sum_j G_{ij}W_{jk}.

矩阵形式为

dX=GW.dX=GW.

shape 检查:

(N×O)(O×I)N×I.(N\times O)(O\times I) \to N\times I.

8. 权重梯度累加所有样本共享路径

权重 WjkW_{jk} 被所有样本行共同使用。

因此

LWjk=iGijXik.\frac{\partial L}{\partial W_{jk}} = \sum_i G_{ij}X_{ik}.

矩阵形式为

dW=GTX.dW=G^TX.

shape 检查:

(O×N)(N×I)O×I.(O\times N)(N\times I) \to O\times I.

样本轴在反向中成为求和收缩轴。

9. 偏置梯度是广播路径求和

前向有

Yij=+bj.Y_{ij}=\cdots+b_j.

同一个 bjb_jNN 个样本位置共享。

所以

dbj=i=1NGij,db_j = \sum_{i=1}^{N}G_{ij},

db=sum(G,dim=0).db=\operatorname{sum}(G,dim=0).

不是因为“偏置固定要沿 dim 0 求和”,而是因为本例的前向广播发生在样本轴。

10. 通用广播规则先从尾轴对齐

两个 shape 广播时:

  1. 从尾轴对齐;
  2. 较短 shape 在左侧补 1;
  3. 对齐轴必须相等或至少一方为 1;
  4. 输出轴大小取较大值。

输入中大小为 1、输出中扩展为更大值的轴,就是前向广播轴。

11. 反向用 sum-to-shape 恢复输入

对广播输入的梯度:

  1. 先按局部导数得到输出 shape 的梯度贡献;
  2. 沿前向由 1 扩展的轴求和;
  3. 必要时 keepdim=True
  4. 移除为对齐而补在左侧的轴;
  5. 检查结果与原输入 shape 完全一致。

这就是“前向广播、反向归约”。

偏置梯度只是它的二维特例。

12. 线性型、二次型与微分复核

线性型

f(x)=aTxf(x)=a^Tx

的梯度是 xf=a\nabla_xf=a,因为每个元素偏导就是对应系数。

二次型

f(x)=12xTAxf(x)=\frac12x^TAx

中,xx 同时出现在左右两侧,两条路径都必须计入:

xf=12(A+AT)x.\nabla_xf=\frac12(A+A^T)x.

AA 对称,则化为 xf=Ax\nabla_xf=Ax。微分法把两条变化写成 df=12dxTAx+12xTAdxdf=\frac12dx^TAx+\frac12x^TAdx,再统一整理为 df=(xf)Tdxdf=(\nabla_xf)^Tdx;它与逐元素路径法应给出同一结果。

15. 矩阵乘积用乘积规则展开微分

Y=ABC,Y=ABC,

dY=dABC+AdBC+ABdC.dY = dA\,BC +A\,dB\,C +AB\,dC.

设上游梯度为

G=YL.G=\nabla_YL.

用 Frobenius 内积

dL=G,dYFdL = \langle G,dY\rangle_F

与迹循环移位,把每项整理为 AL,dAF\langle\nabla_AL,dA\rangle_F 等形式。

16. 三因子乘积梯度

最终得到

AL=GCTBT,\nabla_AL = GC^TB^T,
BL=ATGCT,\nabla_BL = A^TGC^T,
CL=BTATG.\nabla_CL = B^TA^TG.

转置一个乘积时,内部顺序必须反转:

(BC)T=CTBT.(BC)^T=C^TB^T.

每个梯度都应与对应变量同 shape。

17. 注意力分数是批量向量内积网格

对单头注意力:

QRNq×d,KRNk×d.Q\in\mathbb R^{N_q\times d}, \qquad K\in\mathbb R^{N_k\times d}.

分数矩阵为

S=QKTRNq×Nk.S=QK^T \in\mathbb R^{N_q\times N_k}.

SijS_{ij} 是 query ii 与 key jj 的向量内积。

维度 dd 被收缩,query 轴与 key 轴被保留。

batch/head 等前导轴只索引相互独立的矩阵乘任务。

18. 读任意张量乘法的四步法

依次找到共同收缩轴、左输入保留轴、右输入保留轴,再标出 batch 轴与广播规则;同样适用于 GEMM、batched matmul、attention、einsum 与反向公式。

19. 张量 Jacobian 同时保留输出轴与输入轴

Y=f(X),Y=f(X),

完整 Jacobian 的 shape 为

J.shape=Y.shape+X.shape.J.shape=Y.shape+X.shape.

对向量:

Jij=yixj.J_{ij} = \frac{\partial y_i} {\partial x_j}.

对矩阵到矩阵,Jacobain 可能是四阶张量:

Jij,kl=YijXkl.J_{ij,kl} = \frac{\partial Y_{ij}} {\partial X_{kl}}.

它的元素数是输出元素数与输入元素数的乘积。

20. 反向传播计算的是 VJP

标量损失给出上游梯度 gYg_Y

反向沿所有输出轴收缩 Jacobian:

(gX)kl=ij(gY)ijJij,kl.(g_X)_{kl} = \sum_{ij} (g_Y)_{ij} J_{ij,kl}.

这就是 vector–Jacobian product。

行梯度约定写作

gX=gYJ,g_X=g_YJ,

列梯度约定写作

gX=JTgY.g_X=J^Tg_Y.

二者只是向量方向约定不同。

21. 自动微分为何不构造完整 Jacobian

完整 Jacobian 往往巨大且稀疏或结构化。

自动微分系统为每个局部算子实现 backward 规则,直接把上游梯度映射为输入 VJP:

  • matmul backward 变成新的矩阵乘;
  • broadcast backward 变成 sum-to-shape;
  • ReLU backward 变成逐元素 mask;
  • chain rule 通过计算图逐节点组合。

数学上等价于乘 Jacobian,工程上避免显式物化。

对比与决策

1. 推导方法怎样选

  • 依赖路径少、需要建立直觉:逐元素链式法则。
  • 矩阵乘积复杂:微分加 Frobenius 内积与迹。
  • 只需要反向结果:直接写局部 VJP,不构造 Jacobian。
  • 出现广播:先算局部梯度,再 sum-to-shape。

2. 五项自检

任何反向公式都检查:

  1. 前向布局与权重约定;
  2. 上游梯度 shape;
  3. 收缩轴是否正确;
  4. 梯度是否与目标变量同 shape;
  5. 共享或广播路径是否完成求和。

综合训练

编者练习

Y=XWT+bY=XW^T+b,其中 XX32×12832\times128WW256×128256\times128bb256256,上游梯度 GGYY 同 shape。写出 dXdXdWdWdbdb 公式与 shape。

查看参考答案

Y,GR32×256Y,G\in\mathbb R^{32\times256}dX=GWR32×128dX=GW\in\mathbb R^{32\times128}dW=GTXR256×128dW=G^TX\in\mathbb R^{256\times128}db=i=132Gi,:R256db=\sum_{i=1}^{32}G_{i,:}\in\mathbb R^{256}。样本轴在 dWdWdbdb 中被归约。

编者练习 2

张量 AA 的 shape 为 (1,3,1)(1,3,1),与 shape (2,3,4)(2,3,4)BB 做逐元素乘法并得到标量损失。局部输出梯度为 GG。写出 dAdA 的归约轴。

查看参考答案

局部贡献为 GBG\odot B,shape 为 (2,3,4)(2,3,4)AA 在第 0、2 轴由 1 广播到 2、4,所以 dA=sum(GB,dim=(0,2),keepdim=True)dA=\operatorname{sum}(G\odot B,dim=(0,2),keepdim=True),shape 恢复为 (1,3,1)(1,3,1)

编者练习 3

Y=ABCY=ABC,只用 shape 和乘积微分解释为什么 BL=ATGCT\nabla_BL=A^TGC^T

查看参考答案

只保留 BB 的变化有 dY=AdBCdY=A\,dB\,CdL=G,AdBCFdL=\langle G,A\,dB\,C\rangle_F。利用迹循环移位整理为 ATGCT,dBF\langle A^TGC^T,dB\rangle_F,所以梯度为 ATGCTA^TGC^T。左乘 ATA^T 把输出左轴映回 BB 的行轴,右乘 CTC^T 把输出右轴映回 BB 的列轴,结果与 BB 同 shape。

进入下一单元前

  • 已能从标量依赖路径推导线性层 dXdXdWdWdbdb
  • 已能对 ReLU、Sigmoid、逐元素乘写局部 VJP。
  • 已能沿前向广播轴归约梯度并恢复输入 shape。
  • 已能推导线性型、二次型和三因子矩阵乘积梯度。
  • 已能区分 batch、保留与收缩轴。
  • 已能写出张量 Jacobian shape,并说明反向传播为何计算 VJP。
  • 若仍靠背转置,回到单元素路径并做同 shape 检查。
  • 若广播梯度错位,先尾轴对齐 shape,再执行 sum-to-shape。
  • 若想显式构造大 Jacobian,先写元素数并寻找局部 VJP 结构。