Lecture 05 · 让整套 Transformer 共同完成一次预测

让整套 Transformer 共同完成一次预测

课堂接续:T25 · T26 · T27 · T28 · T29 · T30 · T31 · T32 · T33 · T34。连续读本:第4章;本主题提供独立定义、例子、代码与来源。

源句为“我/昨天/给/了/他/一/本/书/。”,九个单位来自本课的教学切分。改用Transformer时,从九个源单位的 embedding 重新建立表示,不能把旧RNN已经算好的 $h_1,\ldots,h_9$ 当成新模型的原始输入。先选“给”这一行:它的query读取各个源位置的key/value,形成属于“给”的输出;再选“他”这一行,保留前一行,另得属于“他”的输出。九个位置都做一次,分数与权重才是9×9,输出仍保留九行。

给行和他行各自读取,再组成九轴self-attention

按行放输入 $X\in\mathbb R^{9\times d}$,同一组共享投影得到 $Q=XW^Q,K=XW^K,V=XW^V$。每个query都对九个来源归一化:$A=\operatorname{softmax}_{key}(QK^\top/\sqrt{d_k})$,$Y=AV$。softmax不沿query轴;所有行也不会被平均为一个句子向量。点积先形成分数,再除以 $\sqrt{d_k}$,最后softmax;不能先归一化再缩放概率。

分数除以根号下key宽度以后再softmax

若无位置、全可见且逐位置共享投影,将输入九行中的我与他交换,输出也按同一置换交换。以P表示置换,$Q'=PQ,K'=PK,V'=PV$,最终 $Y'=PY$,这是等变而非整张输出逐格不变。然而“我给他”与“他给我”关系不同。恢复原句后令第i行输入为 $E[x_i]+p_i$,token交换而位置向量留在各自位置,模型就能把内容与顺序共同用于计算。带固定因果mask时任意置换还改变可见集合,不能照搬全可见推导。

恢复原句后位置固定在格子上,与token向量相加

完整翻译模型有独立的源encoder和目标decoder。九行源embedding加位置,经过encoder后形成源矩阵H;目标输入是右移后的BOS、I、gave、him、a、book、yesterday、句号。源端已收到全部中文,所以可读取全源;gave目标行要预测him,只能读取BOS、I、gave三项目标输入,包括自己。

完整翻译器先接通,gave行的目标mask与右移标签同时约束读取

Encoder每层的多头self-attention把不同来源混入各位置,再经残差与LayerNorm;逐位置FFN把每行通道非线性变换,最后再作残差与LayerNorm。以2017的post-norm写为 $U=\operatorname{LN}_1(X+\operatorname{MHA}(X))$,$Z=\operatorname{LN}_2(U+\operatorname{FFN}(U))$。两个head有各自投影;在同一token位置拼接两头输出,再经 $W^O$ 回到模型宽度。残差是逐元素相加,LayerNorm在单一token的特征轴上计算,不跨句子位置。

完整post-norm块:两头、WO、两次残差归一化与逐位置FFN

FFN可用4→6→4的小尺寸看清扩展、ReLU与投回,所有位置共用同一组参数,但每行独立计算。它不会再直接读取另一个token;上下文已由attention进入这行。$U_i$表示第i个token的整行,$U_{i,r}$才表示第r个通道。下文保留的旧三行、两头数值BLOCK有完整矩阵与代码,独立于当前九单位图;新图解释部件职责,下文从头给出旧算例的每一项数值。

Decoder每层则有三个子层:目标masked self-attention、读取源H的cross-attention、逐位置FFN,各自带残差和归一化。第一种Q/K/V均来自目标表示;第二种Q来自当前目标子层,K/V来自encoder最终H。不能删掉cross-attention以后仍把图叫作同一个源目标分离的翻译器。

目标self-attention、源cross-attention与FFN三个子层保留各自边界

最后decoder表示经词表头得到him的概率。选中him才把它回送,随后生成a、book、yesterday、句号与EOS。训练已知全部右移输入,可在每层同时计算各位置的合法条件概率;自由生成的未来词尚未确定,仍逐步追加。这些依赖与可并行范围是结构事实,翻译质量和速度优势需要在2017当时的数据、预算和硬件条件下判断。

以下旧2×3、六位置整机与三行BLOCK保留完整数学、矩阵、代码和掩码练习。它们各有独立输入;当前九单位整机不借用其数值成绩。

阅读本主题 · 返回实验 · 与Agent共读全文

读本: CLS 02 · Attention 与 Transformer ,查找“让整套 Transformer 共同完成一次预测”;实验中查找“F · 跟着一个 token 穿过完整 encoder block”。

沿一行目标表示走一遍

这一节保留旧R7.1六片段她/her示例与2×3矩阵轴练习。新的九单位self-attention和目标gave→him已在上面完整展开;下文“六行”“her”均属这里定义的旧例。

旧版独立扩展:完整翻译模型的源侧与目标侧

先用一份独立的未缩放点积算例辨认矩阵轴:两项query各读取三个key/value,softmax对每行的三个得分归一化。

旧版独立扩展:两项query分别读取同三个来源,输出保留两行

$$Q=\begin{bmatrix}1&0\\0&1\end{bmatrix},\quad K^\top=\begin{bmatrix}1&0&1\\0&1&1\end{bmatrix},\quad V=\begin{bmatrix}2&0\\0&4\\1&2\end{bmatrix}.$$

$$QK^\top=\begin{bmatrix}1&0&1\\0&1&1\end{bmatrix},\quad A\approx\begin{bmatrix}.422319&.155362&.422319\\.155362&.422319&.422319\end{bmatrix},\quad AV\approx\begin{bmatrix}1.266956&1.466087\\.733044&2.533913\end{bmatrix}.$$

这里的两行分别是query 1与query 2,三列是三个源位置;V与输出的列都是特征轴。两个输出保留各自需求的身份。它是2×3的局部读取,不是完整self-attention。若六个源位置全部产生Q、K、V,每个位置都作为一行query,分数表就是6×6,行列都对应“我/昨天/给了/她/一本/书”;输出仍有六行。

旧版独立扩展:完整源句的六个位置各自提出query,得到六行读取

这组精确值使用未缩放点积。改用2017的scaled dot product时,先对分数除以√d_k,再做softmax:d_k=2时,得分1变成1/√2≈.707107,得分0仍为0,权重随之改变。前面的(.422319,.155362,.422319)因此只属于未缩放条件;后面的多头block会使用缩放条件。

上面的两query例仅解释矩阵轴。完整模型中每个源位置都有自己的query,下一段再沿完整目标路径查看读取的职责。

完整模型使用六段给书句;预测her时合法目标输入到gave为止。先看完整encoder–decoder,再沿目标gave行追到her分布。纯语言模型只用目标前缀;这里的翻译预测还要读取独立的中文源条件。

源端先切分、查embedding并加位置。encoder每层的self-attention能读所有有效源位置,然后残差/归一化,接逐token FFN与另一组残差/归一化。最终源矩阵Z提供跨注意力的K/V。它不直接把“她”的词表ID复制成her;翻译对应需要从数据学习。

目标端输入右移后的BOS/I/gave,也加入位置。在预测her的那一行,masked self-attention可以读这三行输入,不能读将来标准答案里的her。接下来cross-attention的Q来自目标中间表示,K/V来自Z;再经残差、归一化和FFN产生目标hidden,词表头把它投影到所有目标token并softmax。训练可以一次并行算全部右移位置;生成时未知未来输入,只能一步步追加。

把完整单元接回翻译模型

原始 base 模型使用 6 层 encoder、6 层 decoder,$d=512$,8 个 head,$d_k=d_v=64$,FFN 中间宽度 2048。以下维度账忽略 batch,并用源长度 $n$、目标输入长度 $m$:

位置 输入与 Q/K/V 来源 主要形状与输出
源 embedding+位置 源 ID 查表并加位置 $X:n\times512$
Encoder self-attention Q/K/V 均来自本层源表示 每头权重 $n\times n$;输出 $n\times512$
Encoder FFN 每个源位置独立变换 $n\times512\to n\times2048\to n\times512$
Decoder masked self-attention Q/K/V 来自移位后的目标表示 每头权重 $m\times m$,未来 mask
Decoder cross-attention Q 来自当前目标;K/V 来自最终 encoder 输出 每头权重 $m\times n$;输出 $m\times512$
Decoder FFN 每个目标位置独立变换 $m\times512\to m\times2048\to m\times512$
词表投影 最终 decoder 表示 $m\times512$ 乘 $512\times V$,得 $m\times V$ logits

把三个信息范围放在一起看,完整翻译器才闭合。源端已收到整句中文,各位置可以互看;目标端只有合法英文前缀,self-attention遵守因果范围;目标端同时通过cross-attention读取全部已知源句。预测book时,可以读取源侧“书”,却不能把目标侧尚未生成的book提前放进输入。这也说明“能看完整源句”和“不能看未来目标”并不矛盾。

Decoder 的每层有三个子层:masked self-attention、cross-attention、FFN,每个都带自己的残差/归一化。Encoder 只有 self-attention 与 FFN 两类子层。Cross-attention 的 query 来自当前 decoder 子层,key/value 是 encoder 表示的相应投影;不能把一个通用的只有 self-attention 的 block 冒充完整翻译模型。

这条链解释两个易混点。第一,FFN的参数在所有token间共享,但它对每一行独立计算,不承担直接跨词混合;上下文已经由attention进入那一行。第二,残差保留原支路并不让总梯度永远等于1;另一支路、归一化和多层组合仍影响导数。LAB03 F的四维全可见encoder block用精确数值打开这些算子;后面的因果目标侧采用不同可见范围,不能直接挪用全可见例的数值。算子核验与训练后的翻译质量分开评价。

一个完整block的数值与实现

以下BLOCK是独立的三行、四维、两头全可见post-norm构造。当前课堂T31展示部件职责;本节从原输入开始完整复算,不以“课堂已经算过”作为理解前提。

旧版独立扩展:完整post-norm block各阶段数值

两个 head 怎样投影、读取与合并

下面完整展开同一个全可见 post-norm 局部 block 算例,共享输入 X 与全部投影,供独立复算。第一位置也读取后两行;它与因果目标侧只作算子对应,数值不能直接贴回只读自身的目标第一行。

设按行存储的输入 $X\in\mathbb R^{n\times d}$。第 $r$ 个 head 有自己的参数

$$Q_r=XW_r^Q,\quad K_r=XW_r^K,\quad V_r=XW_r^V,$$ $$H_r=\operatorname{softmax}\left(Q_rK_r^\top/\sqrt{d_k}+M\right)V_r.$$

$W_r^Q,W_r^K\in\mathbb R^{d\times d_k}$,$W_r^V\in\mathbb R^{d\times d_v}$。不同 head 可以在不同投影空间计算匹配与内容;不是把完全相同的一张注意力矩阵复制几遍。然后

$$\operatorname{MHA}(X)=\operatorname{Concat}(H_1,\ldots,H_H)W^O,$$

其中拼接结果为 $n\times(Hd_v)$,$W^O\in\mathbb R^{Hd_v\times d}$,输出回到 $n\times d$,才可以与 X 相加。Q/K/V 随输入变化,投影矩阵是训练参数。Cross-attention 只把 Q 的输入换成目标侧表示,K/V 的输入换成 encoder 输出;维度规则相同。

取一个可复算的两头例子:$d=4$,$H=2$,$d_k=d_v=2$,

$$X=\begin{bmatrix}1&0&1&0\\0&1&0&2\\1&1&0&1\end{bmatrix}.$$

三行对应旧独立BLOCK选取的“我、给、书”位置,数值为未训练构造。第一头 Q/K 取输入前两维,V 取后两维;第二头 Q 取后两维,K 取交换次序的前两维,V 取前两维。使用全 attention、无位置和无 dropout。第一个位置在第一头得到约 $(0.401112,0.796664)$,在第二头得到约 $(0.598888,0.802224)$。两头读的是同一组三个位置,却因投影不同而有不同权重和输出;下方可执行代码明确列出全部投影矩阵。

第一位置的读取 我 给 书
head 1 0.401112 0.197776 0.401112
head 2 0.197776 0.401112 0.401112

拼接为 $(a,b,c,d)$ 后,选择一个非平凡的输出投影,把它变成 $(a+c,b+d,a-c,b-d)$:

$$W^O=\begin{bmatrix}1&0&1&0\\0&1&0&1\\1&0&-1&0\\0&1&0&-1\end{bmatrix}.$$

第一个位置的 MHA 输出约为 $(1.000000,1.598888,-0.197776,-0.005560)$。这个构造说明多个头的内容怎样被合并;没有训练证据时,不能把第一头命名为“语法头”、第二头命名为“指代头”并当作真实模型规律。

原输入、残差与单行 LayerNorm

继续前面的两头全可见算例:多头输出已经回到输入宽度,现在将它与原 X 相加,再看每一行怎样归一化。

LayerNorm 对单个位置的 $d$ 个特征计算均值和方差:

$$\mu=\frac1d\sum_{r=1}^d x_r,\qquad \sigma^2=\frac1d\sum_{r=1}^d(x_r-\mu)^2,$$ $$\operatorname{LN}(x)=\gamma\odot\frac{x-\mu}{\sqrt{\sigma^2+\varepsilon}}+\beta.$$

$\gamma,\beta\in\mathbb R^d$ 是可学习缩放与偏移,$\varepsilon>0$ 防止除零并影响数值。这里不跨 token,不跨 batch,也不依赖 batch 中恰好还有哪些句子。归一化后的量经过仿射变换,不必仍为零均值、单位方差;即使省略仿射,epsilon 也使有限值下的方差略有差别。原始定义见 Ba、Kiros 与 Hinton,Layer Normalization。

原始 Transformer encoder 使用 post-norm。省略 dropout 的记号时,一层写成

$$U=\operatorname{LN}_1(X+\operatorname{MHA}(X)),\qquad Z=\operatorname{LN}_2(U+\operatorname{FFN}(U)).$$

训练中原论文还在子层输出上施加 dropout,再走残差和 norm。残差保留旧表示并加上子层计算,使模型不必每层从头重建全部信息。对 $x+F(x)$ 的导数是 $I+J_F$,有直接通路,却不意味着整个 block 的梯度恒为 1;post-norm 后面还有归一化 Jacobian。

接同一个 u:FFN 与第二次 Add & Norm

接着把第一次 Add & Norm 得到的 U 送进 FFN,再合并残差并归一化,走完同一个 post-norm block。 这里 $U$ 是所有位置组成的矩阵,$U_i$ 是第 $i$ 个 token 的整行向量,$U_{i,r}$ 才是该行第 $r$ 个特征;下文第一位置的四个数是 $U_1$ 的四个分量。

Attention 负责跨位置混合,FFN 对每个位置的通道做共享的非线性变换:

$$\operatorname{FFN}(x)=\operatorname{ReLU}(xW_1+b_1)W_2+b_2.$$

$W_1:d\times d_{\mathrm{ff}}$,$W_2:d_{\mathrm{ff}}\times d$。每行独立使用相同参数,因此 FFN 本身不直接从其他 token 读取信息;但它的输入已经可能包含 attention 汇总的内容。两个线性层之间的非线性使整体不退化成一次线性投影。

沿前面的两头例子走完一个位置。第一次残差后得到 $(2.000000,1.598888,0.802224,-0.005560)$。取 $\gamma=1,\beta=0,\varepsilon=1e-05$,第一次 LN 约为 $(1.170705,0.649589,-0.385419,-1.434875)$。FFN 中间宽度取 6,下方代码列出 $W_1\in\mathbb R^{4\times6}$ 与 $W_2\in\mathbb R^{6\times4}$,偏置为零。ReLU 之后的中间表示约为 $(1.170705,0.649589,0.000000,0.000000,0.521116,0.000000)$,投回后为 $(0.585353,0.324795,0.130279,0.000000)$。再加残差并做第二次 LN,最终约为 $(1.233154,0.588798,-0.424732,-1.397220)$。

这些数值来自明确的小算子,不代表模型已经识别某种语义。可以用下面代码复算全部位置,并逐行观察:

import numpy as np
# 参数和检查点由课堂同一 BLOCK 记录生成。
X = np.array([[1, 0, 1, 0], [0, 1, 0, 2], [1, 1, 0, 1]], dtype=np.float64)
WQ1 = np.array([[1, 0], [0, 1], [0, 0], [0, 0]], dtype=np.float64)
WK1 = np.array([[1, 0], [0, 1], [0, 0], [0, 0]], dtype=np.float64)
WV1 = np.array([[0, 0], [0, 0], [1, 0], [0, 1]], dtype=np.float64)
WQ2 = np.array([[0, 0], [0, 0], [1, 0], [0, 1]], dtype=np.float64)
WK2 = np.array([[0, 1], [1, 0], [0, 0], [0, 0]], dtype=np.float64)
WV2 = np.array([[1, 0], [0, 1], [0, 0], [0, 0]], dtype=np.float64)
WO = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [1, 0, -1, 0], [0, 1, 0, -1]], dtype=np.float64)
W1 = np.array([[1, 0, 0, 0, 1, -1], [0, 1, 0, 0, -1, 1], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0]], dtype=np.float64)
W2 = np.array([[0.5, 0, 0, 0], [0, 0.5, 0, 0], [0, 0, 0.5, 0], [0, 0, 0, 0.5], [0, 0, 0.25, 0], [0, 0, 0, 0.25]], dtype=np.float64)
epsilon = 1e-05
def head(Q, K, V):
    S = Q @ K.T / np.sqrt(Q.shape[-1])
    A = np.exp(S - S.max(axis=-1, keepdims=True))
    A /= A.sum(axis=-1, keepdims=True)
    return A, A @ V
def ln(H):
    mean = H.mean(axis=-1, keepdims=True)
    var = ((H - mean)**2).mean(axis=-1, keepdims=True)
    return (H - mean) / np.sqrt(var + epsilon)
A1, H1 = head(X @ WQ1, X @ WK1, X @ WV1)
A2, H2 = head(X @ WQ2, X @ WK2, X @ WV2)
attention = np.concatenate([H1, H2], axis=-1) @ WO
U = ln(X + attention)
ffn = np.maximum(U @ W1, 0) @ W2
Z = ln(U + ffn)
print(A1, A2, attention, U, ffn, Z, sep="\n")

不同长度的 batch 同时需要两种 mask

取两条手工分词源:A=我 昨天 给了 她 一本 书,B=她 笑了 PAD PAD PAD PAD。encoder与cross-attention中,B的位置2至5(从0计)都不可作为有效key。目标训练输入A=BOS I gave her a book,B=BOS she smiled EOS PAD PAD;目标标签B=she smiled EOS PAD PAD PAD,所以只有前三个loss有效。

对目标6×6 scores,causal允许矩阵为:

query位置\key位置 0 1 2 3 4 5
0 读 禁 禁 禁 禁 禁
1 读 读 禁 禁 禁 禁
2 读 读 读 禁 禁 禁
3 读 读 读 读 禁 禁
4 读 读 读 读 读 禁
5 读 读 读 读 读 读

还要叠加每条样本自己的key padding mask。短样本后面的padding query若被算出来,不代表其输出有监督意义;loss会排除。对cross-attention则没有目标式三角mask:每个合法目标query可读取整句已知源,仍要排除源PAD。用同一个“mask”名把这些规则混成一张三角表,会让翻译器错误丢掉右侧源信息。

位置在回答哪个问题

如果只有内容匹配,没有任何位置、顺序或结构信息,将源行共同置换会让输出相应置换,无法由输入排列本身区别“她给我”与“我给她”。加性位置编码把位置向量加到输入,训练可学习利用内容与位置组合;RoPE在每层q/k的匹配中引入旋转。前者和后者进入计算的位置不同,都不能仅凭名字保证长句泛化。

重排一次,再让位置进入计算

旧版独立扩展:没有位置机制时输入与输出共同置换

去掉递推以后,有两个原来容易被计算顺序遮住的问题。第一,输入排列是否仍能影响关系;第二,目标位置是否会提前读到答案。位置表示回答前一个,因果mask与目标移位回答后一个。它们不是同一种装饰,也不能相互替代。

若没有任何位置信号、使用全 attention,且相同投影逐位置共享,重排输入只会相应重排输出。令 $P$ 为置换矩阵,则 $Q'=PQ$、$K'=PK$、$V'=PV$,分数变为 $PSP^\top$;逐行 softmax 后也只重排行列,最终 $Y'=PY$。这叫置换等变,不是置换不变。若再用顺序无关的平均池化,整体分类结果才可能对这种重排不变。

“我给她书”和“她给我书”具有不同关系,模型因此需要知道 token 所处的位置。绝对位置的一种办法是给每个位置一个向量 $p_i$,计算 $X_i=E[x_i]+p_i$。原始 Transformer 使用正弦余弦式,并比较了学习位置向量:

$$\mathrm{PE}(p,2r)=\sin\left(p/10000^{2r/d}\right),\qquad \mathrm{PE}(p,2r+1)=\cos\left(p/10000^{2r/d}\right).$$

不同频率提供不同尺度的位置变化。原始模型还对 token embedding 乘以 $\sqrt d$,再与位置表示相加。能用公式计算超过训练范围的位置,不等于模型在更长序列上的利用能力已得到验证。若用固定 causal mask,任意重排会改变每个位置的可见关系,上述“全 attention 无位置”的等变推导不能原封不动套用。

相对位置可以直接改变配对分数,例如 $S_{ij}=q_i^\top k_j/\sqrt{d_k}+b_{i-j}$,把相对距离信息加到读取偏好中。另一些方法让相对位置向量参与 key 或 value 计算;它们并非同一个公式。Shaw 等,Self-Attention with Relative Position Representations可用于比较这些接口。

RoPE 则在 Q/K 的成对维度上施加与位置相关的旋转。对一个二维列向量对,定义

$$R(\phi)=\begin{bmatrix}\cos\phi&-\sin\phi\\\sin\phi&\cos\phi\end{bmatrix},\quad \widetilde q_i=R(i\theta)q_i,\quad\widetilde k_j=R(j\theta)k_j.$$

则 $\widetilde q_i^\top\widetilde k_j=q_i^\top R((j-i)\theta)k_j$,点积包含相对位移。更高维使用多对维度与不同频率。这里采用的旋转方向决定 $j-i$ 的符号,不能跨实现只看正负号判断错误。RoPE 常作用在 Q/K 上,不是把正弦位置向量加进 embedding 的另一个名字;扩大位置范围或缩放频率还需要任务验证。Su 等,RoFormer,§3。

用完整信息来源区分模型类型

encoder-only如原始BERT,允许表示看整段双向上下文,适合利用已知文本作判断和重建遮盖;decoder-only如原始GPT,用因果前缀学习下一词,生成自然接上;encoder–decoder如原始Transformer/T5,把完整条件输入与自回归输出分开,中间用cross-attention。能看什么与如何训练是两条设计轴,下一主题把三种真实设计的输入和目标摊开。

若“她”变成“他”,先看源是否正确输入、合法信息是否允许到达目标行,再检查读取和词表分数。若batch里某条句子特别容易错,padding或位置错位也是比“架构不行”更可检验的解释。已有F可关一头、改pre/post位置核对前向;完整系统质量和稳定性需要训练证据,不能用一次shape检查代替。

来源:同版读本第四章;M23–M30/M32;Transformer2017 v1 §3。本节中文词界与batch是教学构造,不冒充原论文tokenizer;课堂精确block参数仍来自原共享记录。

非线性不是只由FFN提供

self-attention的softmax以及随输入改变的匹配权重已经使它是非线性计算;不能说“self-attention全是线性的,因此需要FFN才有非线性”。FFN的职责是逐位置做非线性通道加工:同一组权重用于各位置,每行内部混合特征,本身不再跨位置读取。多头提供多组可学习的子空间与读取,不能预先指定每头一种固定词义职业;LayerNorm沿当前token的特征轴统计。

同一图上的训练与生成

训练样本提供全部右移输入,各位置只读其合法前缀,因此同层位置可并行计算。生成时后续token尚未知,选出一个后才能追加并预测下一个。训练并行性没有取消自回归依赖;每层旧K/V为何可复用留给缓存主题。

原课程连续页组:CS224N 2026 Lecture05物理p39–50从循环问题进入顺序与合法目标边界,p53/60/63–66逐步补齐block与encoder–decoder,p67–70再读质量、成本与研究问题。

相邻知识与复核资源

读取之后,系统怎样决定写 him · 同一段文本,三种预训练问题

全部主题 · 关键结果JSON · 只读诊断源码 · Seq2Seq完整实现 · 视觉机制实现 · TinyDecoder与cache实现