RNN(旧方式):电话传话游戏——信息从第一个人耳语给第二个人,再传给第三个人。到最后一个人,最初的话早已失真。长距离依赖几乎不可能准确保留。
Transformer(新方式):圆桌会议——所有人同时能互相看到彼此、互相提问。「真」这个词可以直接"问"「天气」:"你的信息对我有多重要?"不需要中间人转达。
技术实现:每个 token 同时计算它与所有其他 token 的相关性(注意力权重),再加权平均它们的信息。
Query(查询单)):你走进图书馆,心里想的问题——"我需要关于天气的信息"
Key(书脊标签):每本书背面的关键词——"天气" "今天" "预报" ……
Value(书的内容):真正要读的信息。
注意力权重 = 你的 Query 和每个 Key 的匹配度(点积得分 → softmax)。
输出 = 所有 Value 按匹配度加权求和:匹配度越高,这本书贡献越多内容。
一篇文章交给多位编辑同时审阅:语法编辑标注句法关系,内容编辑标注语义依赖,风格编辑标注修辞结构。最终把所有标注合并。
多头注意力 = 并行运行多个独立的 Q/K/V 投影(每个"头"),各自捕捉不同类型的依赖关系,最后拼接后通过 W_O 合并。
本教程简化为单头(single-head)以便数值追踪。
你在白板上写草稿(Self-Attention 的输出),同时保留一张原始便利贴(输入 x)。最后把两者叠加:h_out = Attention(x) + x
作用:① 原始信息不会被"覆盖"丢失;② 梯度反传时有一条高速公路,解决梯度消失。每个 Block 后做两次(Attention 后一次、FFN 后一次)。
Self-Attention 负责"收集信息"(从其他 token 那里汇聚内容);FFN 负责"加工信息"(在每个 token 内部独立地做非线性变换,提炼出更抽象的特征)。
结构:Linear(d_model→d_ff) → ReLU → Linear(d_ff→d_model)。d_ff 通常是 d_model 的 4 倍,给网络更多"加工空间"。
本例 d_model=4, d_ff=8(2倍,便于数值展示)。
语言模型每次只预测下一个 token。"今天天气真___" → 模型给出所有词的概率分布 → 选最高的(或采样)→ 追加到序列 → 再预测下一个……
关键:模型只用最后一个 token(「真」)的隐状态去预测下一词。输出层 logits = h_last · W_out,再 softmax 得概率。
同班同学(同一个 token 的各维度)统一做标准化:减去班级平均分(均值),除以班级标准差。让每层输入的数值范围保持稳定,训练更快更稳。
公式:LN(x) = (x − μ) / σ(γ=1, β=0 本例简化)。对每个 token 向量单独做,不跨 token。
| 参数 | 值 | 说明 |
|---|---|---|
| d_model | 4 | 隐状态维度(真实 GPT-3 = 12288) |
| d_k = d_v | 2 | Q/K/V 投影维度,√d_k = √2 ≈ 1.414 |
| d_ff | 8 | FFN 中间层维度(= 2×d_model) |
| n_layers | 5 | 堆叠 Block 数 |
| vocab_size | 8 | 词表:今天/天气/真/好/坏/晴/不/的 |
| n_tokens | 3 | 输入序列长度 |
| lr | 0.1 | 学习率(梯度下降步长) |
以下是 Block 1 的所有可训练权重(Block 2–5 结构相同但参数不同)。
| 0 | 0 |
| 2 | 0 |
| 0 | 2 |
| 0 | 0 |
| 0 | 0 |
| 2 | 0 |
| 0 | 2 |
| 0 | 0 |
| 1 | 0 |
| 0 | 1 |
| 0 | 0 |
| 0 | 0 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 |
W_Q 的第 3 行 [0, 2] 提取 dim2(强调词维度)→ Q 的第 2 分量。
这使得 Q·K 点积变成"天气内容相似度"的度量:「天气」的 Q/K 幅度最大 → 吸引所有 token 的注意力。
W2 ∈ ℝ8×4:前 4 行构成 0.5 × I₄,后 4 行全 0
效果:FFN(h) ≈ 0.5 × ReLU(h) —— 正分量缩小一半,负分量清零
W_out ∈ ℝ4×8:随机初始化(seed=7, scale=0.3)
今天 天气 真 → 索引 0 索引 1 索引 2
每行对应一个词,每列是一个语义维度:dim0 = 时间词,dim1 = 天气/质量词,dim2 = 强调词,dim3 = 通用信号。
| 索引 | 词 | dim0 (时间) | dim1 (天气/质量) | dim2 | dim3 |
|---|---|---|---|---|---|
| 0 | 今天 | 1.000 | 0.200 | 0.000 | 0.100 |
| 1 | 天气 | 0.200 | 1.000 | 0.000 | 0.100 |
| 2 | 真 | 0.100 | 0.800 | 0.000 | 0.100 |
| 3 | 好(目标词) | 0.000 | 1.200 | 0.000 | 0.100 |
公式:PE[pos, 2i] = sin(pos / 10000^(2i/d_model)),PE[pos, 2i+1] = cos(...)
| pos | Token | dim0 | dim1 | dim2 | dim3 |
|---|---|---|---|---|---|
| 0 | 今天 | 0.000 | 1.000 | 0.000 | 1.000 |
| 1 | 天气 | 0.841 | 0.540 | 0.010 | 1.000 |
| 2 | 真 | 0.909 | −0.416 | 0.020 | 0.999 |
| Token | dim0 | dim1 | dim2 | dim3 |
|---|---|---|---|---|
| 今天 | 1.000+0.000 = 1.000 | 0.200+1.000 = 1.200 | 0.000+0.000 = 0.000 | 0.100+1.000 = 1.100 |
| 天气 | 0.200+0.841 = 1.041 | 1.000+0.540 = 1.540 | 0.000+0.010 = 0.010 | 0.100+1.000 = 1.100 |
| 真 | 0.100+0.909 = 1.009 | 0.800+(−0.416) = 0.384 | 0.000+0.020 = 0.020 | 0.100+0.999 = 1.099 |
W_Q 放大了 dim1:Q 向量第一维 = 2×dim1。所以 Q_天气 = [3.080, 0.020],幅度最大,意味着"天气相关性"最强 → 成为注意力焦点。
公式:Q = X · W_Q,K = X · W_K,V = X · W_V(本例 W_Q = W_K)
√d_k = √2 ≈ 1.414。以「真」为例:
完整 3×3 分数矩阵:
| Query↓ / Key→ | 今天 | 天气 | 真 |
|---|---|---|---|
| 今天 | 4.073 | 5.227 | 1.303 |
| 天气 | 5.227 | 6.708 | 1.674 |
| 真 | 1.303 | 1.674 | 0.418 |
对每行分别做 softmax:指数化后除以行和,确保每行之和为 1。
完整 3×3 注意力权重(颜色深度 ∝ 权重大小):
| Query↓ / Key→ | 今天 | 天气 | 真 |
|---|---|---|---|
| 今天 | 0.2362 | 0.7490 | 0.0148 |
| 天气 | 0.1843 | 0.8105 | 0.0053 |
| 真 | 0.3496 | 0.5061 | 0.1443 |
「真」的注意力分布:天气 50.6%,今天 35.0%,真自身 14.4%。
这意味着「真」最终吸收了 50.6% 来自「天气」的语义内容,用于预测下一词。
每个 token 的新表示 = 各 token 的 V 按注意力权重加权求和:
| Token | C (2维) | 含义 |
|---|---|---|
| 今天 | [1.031, 1.443] | 吸收了 74.9% 天气信息 |
| 天气 | [1.033, 1.471] | 主要是自身信息(81.1%) |
| 真 | [1.022, 1.254] | 50.6% 来自天气,已"知道"天气是核心 |
W_O ∈ ℝ2×4 将 2 维上下文映射回 d_model=4 维:
FFN(h) = W2 · ReLU(W1 · h + b1) + b2
天气:[0.388, 1.397, −1.284, −0.501]
真:[1.202, 0.553, −1.472, −0.284]
注意 dim1 值:今天 1.285 ≈ 天气 1.397 > 真 0.553。「真」经过 Block 1 后 dim1 稍微下降,但在后续 Block 中将逐渐从「天气」吸收质量信息(见页 5)。
2. 「真」的 dim1 持续增长:从 Block 1 的 0.553 增长到 Block 5 的 1.702——不断从「天气」吸收质量信息。
| Q↓ / K→ | 今天 | 天气 | 真 |
|---|---|---|---|
| 今天 | 0.4175 | 0.4420 | 0.1404 |
| 天气 | 0.4197 | 0.4557 | 0.1245 |
| 真 | 0.3770 | 0.3521 | 0.2709 |
「真」隐状态(Block 2 输出)
天气偏向从 50.6% → 35.2%;「真」越来越关注自身,说明 Block 2 开始整合自己的特征
| Q↓ / K→ | 今天 | 天气 | 真 |
|---|---|---|---|
| 今天 | 0.3755 | 0.3828 | 0.2417 |
| 天气 | 0.3778 | 0.3875 | 0.2347 |
| 真 | 0.3559 | 0.3503 | 0.2937 |
「真」隐状态(Block 3 输出)
dim1 从 0.886 → 1.241:「真」的天气/质量特征持续增强
| Q↓ / K→ | 今天 | 天气 | 真 |
|---|---|---|---|
| 今天 | 0.3464 | 0.3476 | 0.3061 |
| 天气 | 0.3470 | 0.3487 | 0.3043 |
| 真 | 0.3413 | 0.3399 | 0.3188 |
「真」隐状态(Block 4 输出)
注意力几乎均匀;dim1 继续增长到 1.546
| Q↓ / K→ | 今天 | 天气 | 真 |
|---|---|---|---|
| 今天 | 0.3352 | 0.3350 | 0.3298 |
| 天气 | 0.3353 | 0.3351 | 0.3296 |
| 真 | 0.3344 | 0.3338 | 0.3318 |
「真」隐状态(Block 5 输出 = h_last)
dim1 = 1.702(Block 1 时为 0.553,增长了 3× )
「真」已完全融合了「天气质量」信息,准备预测「好」。
| Block | dim0 | dim1 (天气/质量) | dim2 | dim3 |
|---|---|---|---|---|
| 1 | 1.202 | 0.553 | −1.472 | −0.284 |
| 2 | 1.050 | 0.886 | −1.315 | −0.621 |
| 3 | 0.705 | 1.241 | −1.162 | −0.783 |
| 4 | 0.214 | 1.546 | −0.974 | −0.785 |
| 5 (h_last) | −0.268 | 1.702 | −0.759 | −0.675 |
W_out ∈ ℝ4×8,每列对应词表中一个词:
| 词 | 索引 | logit | 概率 (softmax) | |
|---|---|---|---|---|
| 今天 | 0 | 0.2666 | 0.1456 | |
| 天气 | 1 | 0.6096 | 0.2053 | |
| 真 | 2 | −0.3024 | 0.0825 | |
| 好 | 3 | 0.6905 | 0.2225 | ← 目标词,最高 logit |
| 坏 | 4 | −0.2668 | 0.0854 | |
| 晴 | 5 | −0.0844 | 0.1025 | |
| 不 | 6 | 0.1146 | 0.1251 | |
| 的 | 7 | −1.2799 | 0.0310 |
对于多分类问题,交叉熵损失只关心目标类别的概率:
参考值:完美预测时 L = 0;随机猜 8 个词时 L = ln(8) ≈ 2.08。当前 1.50 说明已略优于随机猜测。
· 当正确答案概率极低时(p̂ → 0),L → ∞,给出很强的梯度信号
· 与 Softmax 结合后梯度公式非常简洁:δlogits = p̂ − y
· 不匹配信息论中的不确定性度量
· 实际训练收敛慢
即:目标词的梯度 = p̂_好 − 1 = 0.2225 − 1 = −0.7775(负值 → 增大 logit_好)
其余词的梯度 = p̂_i(正值 → 减小其 logit)
这个公式极其简洁,是交叉熵与 Softmax 结合的精华。
公式:δᵢ = ∂L/∂logitᵢ = p̂ᵢ − yᵢ(y 为 one-hot,y₃=1 对应「好」)
今天 天气 真 好← 坏 晴 不 的
「好」的 δ = −0.778 ← 负值代表"这个 logit 需要增大"
其他词 δ > 0 ← 代表"这些 logit 需要减小"
公式:∂L/∂W_out = h_lastT ⊗ δ(外积,shape = 4×8)
以「好」列(索引 3)为例,这一列梯度直接告诉我们 W_out 中哪些权重需要调整:
直觉:h_last 在 dim1(天气质量维度)最大(1.702),增大 W_out[1,3] 能直接提高「好」的 logit。
梯度自动找到了最有效的改进方向!
公式:∂L/∂h_last = W_out · δ(矩阵乘向量,shape = 4)
梯度信号从 Block 5 反向传播至 Block 1,每层经过 FFN、LayerNorm、Self-Attention 的链式法则。
Attention 梯度公式
∂L/∂W_K = XT · ∂L/∂K
∂L/∂W_V = XT · ∂L/∂V
∂L/∂W_O = CT · ∂L/∂O
其中 ∂L/∂Q 需要通过 Softmax 的雅可比矩阵:
∂L/∂S = diag(a)·∂L/∂a − a·(aT·∂L/∂a)
∂L/∂Q = ∂L/∂S · K / √d_k
FFN 梯度公式
∂L/∂W1 = hT · (ReLU'(z)⊙∂L/∂z)
ReLU' = 1(若 z > 0),0(若 z ≤ 0)
残差连接保证梯度同时流过
两条路径(主路 + 捷径),
避免梯度消失。
| 位置 | ‖梯度‖(近似) | 说明 |
|---|---|---|
| 输出层 W_out | ‖δ‖ ≈ 1.00 | 归一化参考 |
| ∂L/∂h_last | 0.631 | 经过 W_out 后 |
| Block 5 → Block 4 | ~0.40 | 经过 LN + FFN |
| Block 4 → Block 3 | ~0.25 | 持续衰减 |
| Block 3 → Block 2 | ~0.15 | |
| Block 1 的 ∂L/∂W_Q | ~0.06 | 最底层梯度最弱,但残差连接减缓了衰减 |
有残差:每个 Block 存在"梯度直通公路"(1 的导数),确保底层 Block 始终能收到有效的梯度信号。
W_new = W_old − 0.1 × ∂L/∂W_out
| 维度 | W_old | 梯度 ∂L/∂W | 更新量 (lr=0.1) | W_new |
|---|---|---|---|---|
| dim0 | +0.1223 | +0.2084 | −0.021 | +0.1014 |
| dim1 ⬆ | −0.0515 | −1.3232 | +0.132 | +0.0809 |
| dim2 | −0.4580 | +0.5899 | −0.059 | −0.5170 |
| dim3 | −0.6865 | +0.5248 | −0.052 | −0.7390 |
这直接增强了"天气/质量特征 → 预测「好」"的连接强度,正是网络需要学到的!
损失对比
损失下降 18.0%(一步梯度下降)
P(好) 对比
「好」的概率提升 +6.94 个百分点
| 指标 | 更新前 | 更新后 | 变化 |
|---|---|---|---|
| 交叉熵损失 L | 1.5026 | 1.2315 | −18.0% |
| P(好) | 22.25% | 29.19% | +6.94pp |
| W_out[dim1, 好] | −0.0515 | +0.0809 | +0.132 ↑ |
| 更新矩阵 | 仅 W_out(lr=0.1,一步) | ||
2. Block 1 自注意力:「真」把 50.6% 注意力给「天气」,开始吸收天气语义
3. Blocks 2-5:注意力趋向均匀,「真」的 dim1 从 0.553 增长到 1.702
4. 输出层:P(好) = 22.25%(最高概率),L = 1.5026
5. 反向传播:梯度从输出层流回,W_out[dim1,好] 的梯度最大(−1.323)
6. 权重更新:一步 SGD 后 L → 1.2315(−18%),P(好) → 29.19%