← 全部章节

P47 · 第 47 讲

Transformer

32:48

本章目录(7 节)
  1. 1. 这一讲解决什么问题
  2. 2. Encoder:把 N 个输入变成 N 个输出
  3. 3. shape 与计算量
  4. 4. 伪代码
  5. 5. 常见误区
  6. 6. 自测
  7. 7. 30 秒速记

课程版本:李宏毅《機器學習 2021》spring,Transformer (上)(2021-03-26) 官方讲义:seq2seq_v9.pdf,60 页 — https://speech.ee.ntu.edu.tw/~hylee/ml/ml2021-course-data/seq2seq_v9.pdf 分P:BV1ou411N7X3?p=47,32:48 来源边界(上下讲切分):讲义页内标题的顺序很清楚:p2 "Sequence-to-sequence (Seq2seq)",p15 "Seq2seq Encoder Decoder",p16–p21 全在 Encoder(p19 Layer Norm、p20 BERT、p21 延伸阅读),p22 标题变为 "Decoder"。据此按讲义章节切:P47 = p1–p21(seq2seq 任务 + encoder),P48 = p22–p59(decoder、cross attention、训练与 tips)。metadata 只有总时长(32:48 / 1:00:34),不能确定视频逐页切点,故标注「讲义章节切分复习版」;无字幕,不引用逐字台词。


1. 这一讲解决什么问题

输入一个序列,输出另一个序列,且输出长度由模型决定(p2)。这句话里有两个"不固定":

p2 列了三类:语音识别(vector sequence → character sequence)、机器翻译、语音翻译(没文字的闽南语语音直接到中文)。p3–p6 的闽南语例子很能说明"seq2seq 到底在学什么":乡土剧只有语音和中文旁白,没有闽南语文字、没有音素标注,讲义连问三遍 "Phonemes of Hokkien? / Background music & noises? / Noisy transcriptions?",答案都是 "Don't care"(p4)——模型直接从"语音序列"学到"中文字符序列",中间不需要人类先定义对齐。p7–p8 是聊天机器人与 QA,p10–p12 把句法树写成括号序列 (S (NP deep learning) (VP is (ADJV very powerful))),p13 多标签分类、p14 目标检测也被塞进 seq2seq 框架。

共同点:输出是一个变长序列,不能用固定维 softmax 一次给出。这就需要一个"读入整段输入"的 encoder 和一个"逐步产生输出"的 decoder。p15 明确把这套结构追溯到 Sutskever 2014 与 Transformer 2017 两条线。


2. Encoder:把 N 个输入变成 N 个输出

p16–p17:输入 \(x_1,\dots,x_N\),encoder 输出 \(h_1,\dots,h_N\)——每个位置一个向量,不是一个汇总向量。这一点常被误解:seq2seq 里确实有过"把整句压成一个 context vector"的做法(P48 的 p46 会看到),但 Transformer encoder 保留每个位置的表示,供 decoder 做 cross attention 时逐位置查询。

p17 右下角还有一句很重要的话:"You can use RNN or CNN." encoder 不是必须用 self-attention;Transformer 的选择是"用 self-attention 取代 recurrence",不是"encoder 只能这样"。

一个 block 里有什么(p18–p19)

p18 画的是一个重复若干层(图中三个 Block 加省略号)的结构:

x → Self-attention → (residual + norm) → FC → (residual + norm) → h

写成式子(\(\mathrm{LN}\) 表示 LayerNorm,\(\mathrm{FFN}\) 是逐位置的前馈网络):

$$ z=\operatorname{SelfAttn}(x),\qquad x_1=\operatorname{LN}(x+z) $$
$$ f=\operatorname{FFN}(x_1),\qquad h=\operatorname{LN}(x_1+f) $$

p19 左侧是残差:\(\mathrm{FC}\) 旁边标着 \(a+b\),即输出 = 子层输出 + 子层输入。右侧是 LayerNorm 的定义:

$$ m=\frac1K\sum_{k=1}^{K}x_k,\qquad \sigma=\sqrt{\frac1K\sum_{k=1}^{K}(x_k-m)^2},\qquad x'_k=\frac{x_k-m}{\sigma} $$

其中 \(K\) 是一个 token 的特征维(不是序列长度,也不是 batch)。p19 图上写的 \(x_1,\dots,x_K\) 是同一位置的不同特征。

数值例:LayerNorm 到底在哪个方向归一(Python 计算)

取一个 token 的 4 维表示 \(x=[1,2,3,4]\):

$$ m=2.5,\quad \sigma=\sqrt{1.25}=1.118034,\quad x'=[-1.3416,\,-0.4472,\,0.4472,\,1.3416] $$

归一化后均值 \(0.0\)、方差 \(1.0\)(脚本输出)。注意:只用了这一个 token 的 4 个数,与 batch 里其他样本无关。

对比 BatchNorm【补充,来自 normalization_v4.pdf p4/p6 的对照】:BN 是对一个 batch 的同一维统计。取 batch 两个样本、2 维:

batch = [[1, 10],
         [3, 14]]
mean_per_dim = [2, 12]      std_per_dim = [1, 2]
normalized   = [[-1, -1],
                [1,  1]]

同样是"减均值除标准差",BN 的均值和方差跨样本、按维;LN 的均值和方差在单样本内跨特征。这个方向差异决定了:序列长度变化、batch 很小甚至 batch=1 时,LN 仍然可用;BN 则需要足够大的 batch 来估统计量。

p21 给了两条延伸阅读:On Layer Normalization in the Transformer Architecture(2002.04745)与 PowerNorm(2003.07845),讨论 Post-LN / Pre-LN 的摆放差异。讲义 p19 的图是 residual 之后 norm(Post-LN);后来的实现常把 norm 放到子层之前(Pre-LN)以稳定深层训练——这是【补充】,讲义只给图与引用,没有展开比较。

p20 用 BERT 说明这套 encoder 的复用:"I use the same network architecture as transformer encoder." 注意这只说架构相同,不代表训练目标相同(BERT 还有 masked language model 预训练),这一句不要过度延伸。

还有两点容易被跳过。第一,encoder 不加因果 mask:它一次性看到整段输入,所以每个 \(h_i\) 都能融合左右两侧;decoder 的自注意力才需要遮住未来(P48)。这正是 encoder 能给 cross attention 提供"双向表示"的原因。第二,堆叠时只有第一层接收 \(x+\text{pos}\),之后每层的输入都是上一层的输出;所有层 shape 相同,但参数各自独立,不共享。

为什么一定要保留 \(N\) 个向量、而不是像旧式 seq2seq 那样压成一个?因为压成一个向量后,decoder 每一步拿到的输入完全相同,输入里的细节只能靠这个定长瓶颈携带;保留 \(N\) 个向量,decoder 每生成一个词都可以重新决定"现在该看输入的哪几个位置"(P48 的 cross attention)。代价是 encoder 输出从 \(d\) 维变成 \(N\times d\),cross attention 的分数矩阵变成矩形。


3. shape 与计算量

设序列长 \(N\)、模型维 \(d\)、FFN 隐层 \(d_{ff}\)(通常 \(4d\)):

位置 shape
输入 \(X\) \(N\times d\)
\(Q,K,V\) \(N\times d_k\)(多头时每头 \(d/M\))
注意力分数 \(N\times N\)
子层输出 \(N\times d\)
FFN 第一层 \(N\times d_{ff}\)
block 输出 \(N\times d\)

(本表按 \(N\times d\) 的行向量约定:每行一个 token。P36/P48 的注意力公式把 token 按列排成 \(d\times N\),两套写法互为转置,\(A'\) 的 softmax 轴也随之从列方向换到行方向,数值等价。)

block 不改变 shape,所以可以堆任意层。计算量的大头是 \(N^2d\)(注意力)与 \(N d^2\)(投影/FFN);序列短时 FFN 占比高,序列长时 \(N^2\) 占主导。

参数量也能这样估(\(d=512\)、\(d_{ff}=2048\)、\(M=8\),Python 计算):

组件 参数量
多头投影 \(W_q,W_k,W_v,W^O\) \(4d^2\) = 1,048,576
FFN \(d\to d_{ff}\to d\) \(2d\,d_{ff}\) = 2,097,152
单个 block 合计 3,145,728
若堆 6 层(仅估算示例) 18,874,368(约 \(1.887\times10^7\))

可以看到 FFN 占了三分之二——"Transformer 的参数主要在 FFN,不在 attention"这句话就是从这个比例来的。多头并不增加总参数:8 个头每头 64 维,拼起来仍是 \(d\) 维,\(W^O\) 还是 \(d\times d\)。


4. 伪代码

def encoder_block(x, Wq, Wk, Wv, Wo, W1, b1, W2, b2):
    z = multi_head_attention(x, Wq, Wk, Wv, Wo)   # (N,d)
    x = layer_norm(x + z)                          # residual + norm
    f = relu(x @ W1 + b1) @ W2 + b2                # 逐位置 FFN
    return layer_norm(x + f)                       # (N,d)

h = x
for _ in range(num_layers):
    h = encoder_block(h, ...)

5. 常见误区

  1. "encoder 把整句压成一个向量"。Transformer encoder 输出 \(N\) 个向量;"压成一个"是旧式 seq2seq 的 context vector,二者不要混。
  2. "LayerNorm 就是 BatchNorm 换个名字"。归一化方向不同:LN 在单样本内跨特征,BN 跨样本按维。数值例已给出两种结果。
  3. "residual 只是让梯度好传"。它同时保留了下层信息,使每个 block 学的是增量;去掉残差,深层 encoder 很难训。
  4. "self-attention 本身知道位置"。不知道(P37 p29 的置换实验);encoder 必须额外加 positional encoding,否则句序信息在进入第一个 block 时就丢了。
  5. "encoder 必须用 self-attention"。p17 明说可以用 RNN 或 CNN;选 self-attention 是为了并行与长距离,不是定义要求。
  6. "Post-LN 和 Pre-LN 等价"。摆放位置影响深层训练稳定性;讲义图是 Post-LN,延伸阅读讨论的是这个选择。

6. 自测

Q1. encoder 输入 \(N=20\)、\(d=512\),\(M=8\) 头。注意力分数矩阵多大?每个头的 \(d_k\) 是多少?

答案

分数矩阵 \(20\times20\)(每个头一个,共 8 个);每头 \(d_k=d_v=512/8=64\)。注意 \(N\times N\) 与 \(d\) 无关,长序列时它是主要开销。

Q2. 对一个 token 的表示 \([2,4,6,8]\) 做 LayerNorm(总体标准差),结果是什么?如果对 batch 里两个样本的同一维做 BN,统计量会不同吗?

答案

均值 5,偏差 \([-3,-1,1,3]\),方差 \((9+1+1+9)/4=5\),\(\sigma=2.236\),结果为 \([-1.3416,-0.4472,0.4472,1.3416]\)。BN 会用两个样本在该维上的均值/标准差,数值取决于另一个样本;LN 不会。

Q3. 为什么 encoder block 里每个子层后面都要 residual?如果去掉,可能发生什么?

答案

残差让子层只需学"相对于输入的修改量",并为梯度提供一条恒等路径。去掉后,深层堆叠时梯度要穿过每个子层的雅可比连乘,容易出现退化/难训;同时下层的有用信息也没有旁路保留。

Q4. p20 说 BERT 用了"同样的 encoder 架构",能否据此说 BERT 就是 Transformer encoder?

答案

不能。相同的是 block 结构(self-attention + FFN + residual + LN);不同的是训练目标(BERT 有 masked LM / next sentence 等预训练)与使用方式。讲义这句话是在讲架构复用,不是在讲训练方法等价。


7. 30 秒速记

seq2seq:输入序列 → 输出序列,输出长度由模型决定,所以不能用一个固定 softmax。encoder 把 \(N\) 个输入变成 \(N\) 个 \(d\) 维表示;每个 block = 多头 self-attention + residual + LayerNorm,再 + 逐位置 FFN + residual + LayerNorm,shape 不变所以能堆。LayerNorm 在单个 token 的特征维上算均值/方差(\([1,2,3,4]\to[-1.34,-0.45,0.45,1.34]\)),与 batch 无关;BN 才是跨样本按维。encoder 也可以用 RNN/CNN(p17),self-attention 不是定义。

跨 P 连接:P36/P37 给了 self-attention 与多头/位置编码,这一讲把它们组装成 encoder block;P48 从 p22 起讲 decoder——自回归、因果 mask、cross attention(Q 来自 decoder、K/V 来自 encoder)、teacher forcing 与 exposure bias。P38 的 RNN 是 p17 所说的另一种 encoder 选择,也是理解"为什么要去掉 recurrence"的对照。


引用页(PDF 物理页,1 起)

p2(seq2seq 定义与输出长度)、p3–p8(语音/翻译/TTS/ chatbot/QA)、p10–p14(parsing、多标签、检测)、p15–p17(encoder-decoder 框架、逐位置输出、可用 RNN/CNN)、p18(block 结构)、p19(residual 与 LayerNorm 公式)、p20(BERT 复用架构)、p21(Post-/Pre-LN 延伸阅读)。

来源与说明

基于对应官方讲义整理,未取到完整视频字幕;不冒充逐字稿。