Transformer - day02- Decoder

原始Transformer架构

序号 环节 英文名称 作用
1 输入嵌入层 Input Embedding 将输入词元转为向量
2 位置编码 Positional Encoding 注入序列位置信息
3 编码器 Encoder 由6层相同结构堆叠,负责理解输入序列
4 解码器 Decoder 由6层相同结构堆叠,负责生成输出序列
5 输出映射层 Linear + Softmax 将解码器输出转为最终词的概率分布

此外,在现代深度学习语境中,“Transformer”已演变为一个大家族:

  • 仅编码器(Encoder-Only):如 BERT,适合分类、理解任务。
  • 仅解码器(Decoder-Only):如 GPT,适合生成任务。
  • 编码器-解码器(Encoder-Decoder):如原始Transformer、T5,适合序列到序列任务(如翻译、摘要)。

解码器 Decoder

输出嵌入(Output Embedding)

  • 在原始 Transformer 中,输出嵌入层(Output Embedding) 和 解码器最后的线性层(Linear Layer / Softmax 前的投影层) 是共享权重(Weight Tying)的,只是转置使用
  • 作用:
    • 输入是 目标(结果)序列,将其 映射固定维度的向量

位置编码(Positional Encoding)

  • 同 编码器 环节,目标序列注入位置信息(顺序)
  • 使用正弦/余弦函数或可学习参数 (函数形式参考前面编码器)

带掩码的多头自注意力(Masked Multi-Head Self-Attention)

  • 解码器 层的 第 1 个 子层
  • 计算目标 序列内部 词与词 之间的依赖关系
  • 掩码(Mask)
    • 确保在预测第 t 个词时,只能看到第 1 到 t-1 个词(已生成的词)

输入

  • 来自上一环节,即解码器经过 嵌入编码、位置编码后 的结果
  • 形状
    • batch_size × 目标序列长度 × d_model ,例如:(32, 6, 512)
      • batch_size 是你自己定义的 批次大小,赋值多大看前面编码器,影响计算效率
      • 6 根据你的训练集情况赋值,即 你训练集的目标结果的 最大 长度
      • d_model 也是你自己定义的,看前面Encoder的举例,d_model= 512

中间件(转换过程,5个步骤)

STEP 1:线性变换并拆解多头(与编码器相同)

  • 输入矩阵 X(形状 32, 6, 512)分别乘以三个权重矩阵 \(W_Q, W_K, W_V\),得到 Q、K、V
  • 将 Q、K、V 在特征维度上拆成 h=8 个头,每个头的形状变为 (32, 6, 64)
  • 举例:
参数 说明
批次大小 Batch = 1 只处理这一句
序列长度 L = 4 对应解码器输入:, I, love, AI)
模型维度 d_model = 4 就是前面例子中的512,为了简化计算这里改成了4
多头数 h = 2 所以每个头的维度 \(d_k = d_v = 4/2 = 2\)
  • 假设:输入矩阵 X(形状 4×4),由“输出嵌入 + 位置编码”得到
位置 参数 说明
位置0 <(START)> [1.0, 0.5, 0.0, 0.5]
位置1 (I) [0.8, 0.6, 0.2, 0.4]
位置2 (love) [0.2, 0.9, 0.3, 0.1]
位置3 (AI) [0.4, 0.7, 0.5, 0.2]
  • 计算 Q、K、V(拆解成2个头)
    • 我们假设经过权重矩阵 \(W_Q, W_K, W_V\) 计算后,得到了每个头的 \(Q、K、V\)(形状 4×2)
    • 为了演示第4步的掩码的作用过程,我们只看 头1(Head 1) 的数据
位置 头1的 Q 矩阵 (4×2) 头1的 K 矩阵 (4×2) 头1的 V 矩阵(4×2)
位置0 [1.0, 0.5] [0.9, 0.4] [0.2, 0.8]
位置1 [0.8, 0.6] [0.7, 0.5] [0.5, 0.3]
位置2 [0.2, 0.9] [0.3, 0.8] [0.7, 0.1]
位置3 [0.4, 0.7] [0.5, 0.6] [0.4, 0.6]

STEP2 :计算原始注意力分数(Scores)

  • 计算 \(Scores = Q · K^T\)(暂时忽略除以 \(\sqrt(d_k)\) 的缩放,这不影响掩码逻辑
  • 结果是一个 4×4 的矩阵
  • 行代表当前位置(查询 Q),列代表所有位置(键 K),原始分数矩阵(4×4)
查询\键 位置0 (START) 位置1 (I) 位置2 (love) 位置3 (AI)
位置0 \(1.0*0.9+0.5*0.4 = 1.1\) 0.95 0.70 0.80
位置1 \(0.8*0.9+0.6*0.4 = 0.96\) 0.86 0.72 0.76
位置2 \(0.2*0.9+0.9*0.4 = 0.54\) 0.59 0.78 0.64
位置3 \(0.4*0.9+0.7*0.4 = 0.64\) 0.63 0.68 0.62
  • 注意:第 2 行(love)对应第 3 列(AI)的分数是 0.64,说明如果不加掩码,模型在理解“love”时,会关注到未来的“AI”;其他同理

STEP 3 :应用未来掩码(Masking)

  • 用代码 生成一个 上三角掩码矩阵,将所有 列索引(j) > 行索引(i) 的位置替换为 -inf(负无穷)

掩码后的 Scores矩阵:

查询\键 位置0 (START) 位置1 (I) 位置2 (love) 位置3 (AI)
位置0 1.1 -inf -inf -inf
位置1 0.96 0.86 -inf -inf
位置2 0.54 0.59 0.78 -inf
位置3 0.64 0.63 0.68 0.62

STEP 4 :Softmax 归一化(权重变为概率)-- 所谓 激活

  • 对每一行执行 \(Softmax(t)=\frac{1}{1+e^{-t}}\),所有未来位置的权重直接变成 0
位置权重 说明 近似计算
位置0 的权重 只能看到自己 \([1.0, \color{red}{0}, \color{red}{0}, \color{red}{0}]\)
位置1 的权重 只关注位置0和1 \([0.52, 0.48, \color{red}{0}, \color{red}{0}]\)
位置2 的权重 只关注位置0、1、2 \([0.30, 0.32, 0.38, \color{red}{0} ]\)
位置3 的权重 没有被遮住任何位置 \([0.24, 0.23, 0.26, 0.27]\)

STEP 5 :加权聚合(计算最终输出 Z)

  • 前面计算过 头1 的 V 矩阵(4×2),V 矩阵如下:
    \(V =\begin{bmatrix} 0.2 & 0.8 \\ 0.5 & 0.3 \\ 0.7 & 0.1\\ 0.4 & 0.6 \end{bmatrix}\)
  • 计算 \(Z = 权重矩阵 · V\),权重矩阵来自上面 第5步Softmax归一化 的结果
对于 头1,计算输出 Z1(4×2)
  • \(Z_1[i] = 权重矩阵第i行 · V矩阵\)

  • 位置0 的输出:

    • \(1.0*[0.2, 0.8] + \color{red}{0}*[0.5,0.3] + \color{red}{0}*[0.7,0.1] + \color{red}{0}*[0.4,0.6] = \color{red}{[0.2, 0.8]}\)
  • 位置1 的输出:

    • \(0.525*[0.2,0.8] + 0.475*[0.5,0.3] = [0.105+0.2375, 0.42+0.1425] = \color{red}{[0.3425, 0.5625]}\)
  • 位置2 的输出:

    • \(0.302*[0.2,0.8] + 0.316*[0.5,0.3] + 0.382*[0.7,0.1] = [0.0604+0.158+0.2674, 0.2416+0.0948+0.0382] = \color{red}{[0.4858, 0.3746]}\)
  • 位置3 的输出:

    • \(0.250*[0.2,0.8] + 0.247*[0.5,0.3] + 0.259*[0.7,0.1] + 0.244*[0.4,0.6] = [0.05+0.1235+0.1813+0.0976, 0.2+0.0741+0.0259+0.1464] = \color{red}{[0.4524, 0.4464]}\)
  • 因此,头1的输出矩阵 Z1 为:
    \(Z_1 =\begin{bmatrix} 0.2 & 0.8 \\ 0.3425 & 0.5625 \\ 0.4858 & 0.3746\\ 0.4524 & 0.4464 \end{bmatrix}\)

对于 头2,计算输出 Z2(4×2)
  • \(Z_2[i] = 权重矩阵第i行 · V矩阵\)
头2 注意力权重矩阵(4×4) V矩阵(4×2)
\(\begin{array} \\位置0\\位置1\\位置2\\位置3 \end{array}\) \(\begin{bmatrix} 1.0&0&0&0\\0.562&0.438&0&0\\0.343&0.382&0.275&0\\0.282&0.187&0.318&0.213\end{bmatrix}\) \(\begin{bmatrix} 0.3& 0.5 \\0.8& 0.2\\0.1& 0.7\\0.6& 0.4\end{bmatrix}\)
  • 位置0 的输出:

    • \(1.0*[0.3, 0.5] = \color{red}{[0.3, 0.5]}\)
  • 位置1 的输出:

    • \(0.562*[0.3,0.5] + 0.438*[0.8,0.2] = [0.1686+0.3504, 0.281+0.0876] = \color{red}{[0.519, 0.3686]}\)
  • 位置2 的输出:

    • \(0.343*[0.3,0.5] + 0.382*[0.8,0.2] + 0.275*[0.1,0.7] = [0.1029+0.3056+0.0275, 0.1715+0.0764+0.1925] = \color{red}{[0.436, 0.4404]}\)
  • 位置3 的输出:

    • \(0.282*[0.3,0.5] + 0.187*[0.8,0.2] + 0.318*[0.1,0.7] + 0.213*[0.6,0.4] = [0.0846+0.1496+0.0318+0.1278, 0.141+0.0374+0.2226+0.0852] = \color{red}{[0.3938, 0.4862]}\)
  • 因此,头2的输出矩阵 Z2 为:
    \(Z_2 =\begin{bmatrix} 0.3& 0.5 \\ 0.519& 0.3686 \\ 0.436& 0.4404\\ 0.3938& 0.4862 \end{bmatrix}\)

STEP 6 :多头拼接与输出

  • 头1和头2执行完全相同的计算(只是 Q、K、V 矩阵不同)
  • 将两个头的输出(每个 4×2)在特征维度上拼接,得到 4×4 的矩阵,
  • 乘以输出投影矩阵 \(W_O\),最终得到 带掩码自注意力层的最终输出
    形状依然是 4×4
STEP 1 :拼接(Concat)
  • 将头1的输出 Z1(4×2)和头2的输出 Z2(4×2)在特征维度(列)上拼接,得到 Z_concat(4×4)

\(Z_{concat}= [Z_1\ |\ Z_2]=\begin{bmatrix} 0.2 & 0.8 & 0.3 & 0.5 \\0.3425 & 0.5625 & 0.519 & 0.3686 \\ 0.4858 & 0.3746 & 0.436 & 0.4404 \\0.4524 & 0.4464 & 0.3938 & 0.4862 \end{bmatrix}\)

STEP 2 :输出投影(乘以 \(W_O\)
  • 拼接结果 乘以输出投影矩阵 \(W_O\)(4×4)

  • 计算最终输出 $ Output_{Final} = Z_{concat} · W_{O} $

  • 假设
    \(W_O = \begin{bmatrix} 0.5& 0.3& 0.2& 0.0 \\ 0.1& 0.6& 0.1& 0.2 \\ 0.0& 0.2& 0.5& 0.3 \\ 0.4& 0.0& 0.2& 0.4 \end{bmatrix}\)

  • 位置0 的输出(\(Z_{concat}[0] = [0.2, 0.8, 0.3, 0.5]\)):

    • 列0:\(0.2*0.5 + 0.8*0.1 + 0.3*0 + 0.5*0.4 = 0.10+0.08+0+0.20 = 0.38\)
    • 列1:\(0.2*0.3 + 0.8*0.6 + 0.3*0.2 + 0.5*0 = 0.06+0.48+0.06+0 = 0.60\)
    • 列2:\(0.2*0.2 + 0.8*0.1 + 0.3*0.5 + 0.5*0.2 = 0.04+0.08+0.15+0.10 = 0.37\)
    • 列3:\(0.2*0 + 0.8*0.2 + 0.3*0.3 + 0.5*0.4 = 0+0.16+0.09+0.20 = 0.45\)
    • 结果:\(\color{red}{\begin{bmatrix} 0.38& 0.60& 0.37& 0.45 \end{bmatrix}}\)
  • 位置1 的输出(\(Z_{concat}[1] = [0.3425, 0.5625, 0.519, 0.3686]\)):

    • 列0:\(0.3425*0.5 + 0.5625*0.1 + 0.519*0 + 0.3686*0.4 = 0.17125+0.05625+0+0.14744 = 0.37494\)
    • 列1:\(0.3425*0.3 + 0.5625*0.6 + 0.519*0.2 + 0.3686*0 = 0.10275+0.3375+0.1038+0 = 0.54405\)
    • 列2:\(0.3425*0.2 + 0.5625*0.1 + 0.519*0.5 + 0.3686*0.2 = 0.0685+0.05625+0.2595+0.07372 = 0.45797\)
    • 列3:\(0.3425*0 + 0.5625*0.2 + 0.519*0.3 + 0.3686*0.4 = 0+0.1125+0.1557+0.14744 = 0.41564\)
    • 结果:\(\color{red}{\begin{bmatrix} 0.37494& 0.54405& 0.45797& 0.41564 \end{bmatrix}}\)
  • 位置2 的输出(\(Z_{concat}[2] = [0.4858, 0.3746, 0.436, 0.4404]\)):

    • 列0:\(0.4858*0.5 + 0.3746*0.1 + 0.436*0 + 0.4404*0.4 = 0.2429+0.03746+0+0.17616 = 0.45652\)
    • 列1:\(0.4858*0.3 + 0.3746*0.6 + 0.436*0.2 + 0.4404*0 = 0.14574+0.22476+0.0872+0 = 0.45770\)
    • 列2:\(0.4858*0.2 + 0.3746*0.1 + 0.436*0.5 + 0.4404*0.2 = 0.09716+0.03746+0.218+0.08808 = 0.44070\)
    • 列3:\(0.4858*0 + 0.3746*0.2 + 0.436*0.3 + 0.4404*0.4 = 0+0.07492+0.1308+0.17616 = 0.38188\)
    • 结果:\(\color{red}{\begin{bmatrix} 0.45652& 0.45770& 0.44070& 0.38188 \end{bmatrix}}\)
  • 位置3 的输出(\(Z_{concat}[3] = [0.4524, 0.4464, 0.3938, 0.4862]\)):

    • 列0:\(0.4524*0.5 + 0.4464*0.1 + 0.3938*0 + 0.4862*0.4 = 0.2262+0.04464+0+0.19448 = 0.46532\)
    • 列1:\(0.4524*0.3 + 0.4464*0.6 + 0.3938*0.2 + 0.4862*0 = 0.13572+0.26784+0.07876+0 = 0.48232\)
    • 列2:\(0.4524*0.2 + 0.4464*0.1 + 0.3938*0.5 + 0.4862*0.2 = 0.09048+0.04464+0.1969+0.09724 = 0.42926\)
    • 列3:\(0.4524*0 + 0.4464*0.2 + 0.3938*0.3 + 0.4862*0.4 = 0+0.08928+0.11814+0.19448 = 0.40190\)
    • 结果:\(\color{red}{\begin{bmatrix} 0.46532, 0.48232, 0.42926, 0.40190 \end{bmatrix}}\)

最终输出结果(形状 4×4)

  • 经过 带掩码的多头自注意力 全部计算后,该子层的最终输出矩阵为

\({Output}_{Final} = \begin{bmatrix} 0.38& 0.60& 0.37& 0.45\\ 0.37494& 0.54405& 0.45797& 0.41564\\ 0.45652& 0.45770& 0.44070& 0.38188\\ 0.46532& 0.48232& 0.42926& 0.40190 \end{bmatrix}\)

输出

  • 4×4 矩阵

输出的 \({Output}_{Final}\) 先做 Add & Norm 处理

  • Add & Norm 参见 编码器 内容
  • 原始输入 X经过掩码注意力后的输出 相加,再标准化
    • 原始输入 X(来自输出嵌入+位置编码,形状 4×4)
      \(X = \begin{bmatrix} 1.0& 0.5& 0.0& 0.5\\ 0.8& 0.6& 0.2& 0.4\\ 0.2& 0.9& 0.3& 0.1\\ 0.4& 0.7& 0.5& 0.2 \end{bmatrix}\)

    • 掩码自注意力输出 Final_Output(上一步算出的,形状 4×4)
      \({Output}_{Final} = \begin{bmatrix} 0.38& 0.60& 0.37& 0.45\\ 0.37494& 0.54405& 0.45797& 0.41564\\ 0.45652& 0.45770& 0.44070& 0.38188\\ 0.46532& 0.48232& 0.42926& 0.40190 \end{bmatrix}\)

残差连接(Add):Sum = X + Final_Output

  • 逐元素相加,形状仍为 4×4
    \(Sum = \begin{bmatrix} 1.38& 1.10& 0.37& 0.95\\ 1.1749& 1.1441& 0.6580& 0.8156\\ 0.6565& 1.3577& 0.7407& 0.4819\\ 0.8653& 1.1823& 0.9293& 0.6019 \end{bmatrix}\)

层归一化(Layer Norm)

  • 对 Sum 的 每一行 独立做标准化
  • 这里省略繁琐的 $ (x-μ)/σ$ 计算,直接给出归一化后的结果 Out1
  • 解码器一共重复 6 次,这里只是 第 1 次 的 第 1 子层 的结果 Out1
    \(Out1 = \begin{bmatrix} 1.12& 0.45& -1.34& 0.77\\ 0.85& 0.72& -1.21& 0.64\\ -0.62& 1.38& -0.85& 0.09\\ -0.35& 1.05& 0.18& -0.88 \end{bmatrix}\)

得到的结果,作为 Q1

  • 形状仍然保持了原来的 4×4
  • 然后和 编码器的 K1, V1,做 交叉注意力(Cross-Attention)

编码器-解码器注意力(Cross-Attention / Encoder-Decoder Attention)

  • 解码器独有的环节,负责把 英文生成进度中文源语言语义 对齐

输入

  • 查询(Q):来自解码器上一步的输出 Out1
    • 形状 4×4,代表英文端 [ START, I, love, AI ] 的当前状态
  • 键(K)和值(V):来自编码器的最终输出 Enc_Out
    • 形状 3×4,代表中文端 [ 我, 爱, AI ] 的语义

假设编码器之前输出的 Enc_Out 为(形状 3×4):

\(Enc\_Out = \begin{bmatrix} 0.5& 0.3& 0.9& 0.2\\ 0.8& 0.6& 0.4& 0.7\\ 0.1& 0.5& 0.3& 0.8 \end{bmatrix}\)

  • 第 1 行,[0.5, 0.3, 0.9, 0.2],# 对应中文 "我"
  • 第 2 行,[0.8, 0.6, 0.4, 0.7],# 对应中文 "爱"
  • 第 3 行,[0.1, 0.5, 0.3, 0.8],# 对应中文 "AI"

中间转换过程(共 2×4 步)-- 交叉注意力计算

STEP 1 : 计算注意力分数 \(Scores\_cross = Q · K^T\)

  • 这里用 Out1 直接作为Q,用 Enc_Out 直接作为K
  • 形状是 4×3,行(4个英文位置) × 列(3个中文词)
    • 算第 0 行(英文 对中文三个词的分数):
      • START 向量 [1.12, 0.45, -1.34, 0.77] 分别点乘中文三个向量:
        • 对“我”:\(1.12*0.5 + 0.45*0.3 + (-1.34)*0.9 + 0.77*0.2 = 0.56+0.135-1.206+0.154 = -0.357\)
        • 对“爱”:\(1.12*0.8 + 0.45*0.6 + (-1.34)*0.4 + 0.77*0.7 = 0.896+0.27-0.536+0.539 = 1.169\)
        • 对“AI”:\(1.12*0.1 + 0.45*0.5 + (-1.34)*0.3 + 0.77*0.8 = 0.112+0.225-0.402+0.616 = 0.551\)
    • 第 0 行分数为 \([-0.357\ \ \ \ 1.169\ \ \ \ 0.551]\)
    • 做 Softmax 得到权重 \([0.12\ \ \ \ 0.58\ \ \ \ 0.30]\)(最关注“爱”)

STEP 2 : 用这个权重去加权聚合 V

  • 这里 V 也直接使用 Enc_Out 的值
  • \(加权输出_{第 0 行} = 0.12*[0.5,0.3,0.9,0.2] + 0.58*[0.8,0.6,0.4,0.7] + 0.30*[0.1,0.5,0.3,0.8]\)
  • \(加权输出_{第 0 行} = [0.06+0.464+0.03, 0.036+0.348+0.15, 0.108+0.232+0.09, 0.024+0.406+0.24]\)
  • \(加权输出_{第 0 行} = [0.554,\ \ \ \ 0.534,\ \ \ \ 0.430,\ \ \ \ 0.670]\)

重复上述 STEP 1 和 STEP 2,计算剩余的

  • 上面计算了 第 0 行,还剩余的是:第1、2、3行
  • 得到 交叉注意力输出 Cross_Out(形状 4×4)
    \(Cross\_Out = \begin{bmatrix} 0.554& 0.534& 0.430& 0.670\\ 0.620& 0.480& 0.510& 0.590\\ 0.440& 0.560& 0.490& 0.630\\ 0.510& 0.520& 0.470& 0.600 \end{bmatrix}\)
  • 形状变化
    • (4×4) · (4×3) = (4×3) → Softmax → (4×3) · (3×4) = (4×4)
    • 完美保持了维度不变

子层 残差连接 + 层归一化(Add & Layer Norm)

子层 残差连接

  • 子层2的输入 Out1 与 交叉注意力输出 Cross_Out 相加
    • \(Sum2 = Out1 + Cross_Out\)
  • 做 LayerNorm 得到 Out2(形状 4×4)
    \(Out2 = \begin{bmatrix} 0.85& 0.50& -0.75& 1.20\\ 0.90& 0.70& -0.60& 1.10\\ 0.40& 1.00& -0.40& 0.80\\ 0.60& 0.90& -0.20& 0.70 \end{bmatrix}\)

前馈网络(Feed-Forward Network,FFN)

  • 这一步对 每个位置 独立进行 非线性 变换
  • 线性变换 --> ReLU 激活 --> 线性变换
  • \(FFN(x) = ReLU(x·W_1 + b_1)·W_2 + b_2\)

计算举例

  • 与前面对应,\(d\_model = 4\)
  • \(d\_ff = \color{red}8\)(原论文中是 2048,这里为了演示缩小比例)
  • 定义 可训练权重矩阵 \(W_1, W_2\)偏置向量 \(b_1, b_2\)
    • 第 1 层权重 \(W_1\)(形状 \(d_{model} × d_{ff}\),这里是 4×8)
      \(W_1 = \begin{bmatrix} 0.1& 0.2& 0.3& 0.0& 0.1& -0.1& 0.2& 0.0\\ 0.0& 0.1& -0.1& 0.2& 0.3& 0.0& 0.1& 0.2\\ 0.2& 0.0& 0.1& -0.1& 0.0& 0.2& 0.3& 0.1\\ 0.1& -0.1& 0.0& 0.2& 0.1& 0.0& -0.1& 0.3 \end{bmatrix}\)

    • 第 1 层偏置 \(b_1\)(长度 \(d_{ff}\),这里是 8)
      \(b_1 = [0.1,\ \ \ \ 0.0,\ \ \ \ 0.1,\ \ \ \ -0.1,\ \ \ \ 0.0,\ \ \ \ 0.1,\ \ \ \ 0.0,\ \ \ \ -0.1]\)

    • 第 2 层权重 \(W_2\)(形状 \(d_{ff} × d_{model}\),这里是 8×4)
      \(W_2 = \begin{bmatrix} 0.1& 0.2& 0.0& 0.1\\ 0.0& 0.1& 0.2& 0.0\\ 0.2& 0.0& 0.1& 0.2\\ 0.1& 0.1& 0.0& 0.3\\ 0.0& 0.2& 0.1& 0.0\\ 0.3& 0.0& 0.1& 0.2\\ 0.1& 0.2& 0.0& 0.1\\ 0.0& 0.1& 0.2& 0.0 \end{bmatrix}\)

    • 第 2 层偏置 \(b_2\)(长度 \(d_{model}\),这里是 4)
      \(b_2 = [0.1,\ \ \ \ 0.0,\ \ \ \ 0.1,\ \ \ \ -0.1]\)

STEP 1 :第 1 次 线性变换

  • 计算 \(Z = Out2 · W1 + b1\)(形状 4×8)
    \(Z = \begin{bmatrix} 0.155& 0.10& 0.23& 0.315& 0.355& -0.135& -0.125& 0.285\\ 0.18& 0.14& 0.24& 0.32& 0.41& -0.11& -0.04& 0.31\\ 0.14& 0.10& 0.08& 0.30& 0.42& -0.02& -0.02& 0.30\\ 0.19& 0.14& 0.17& 0.24& 0.40& 0.0& 0.08& 0.27 \end{bmatrix}\)

STEP 2 :ReLU 函数 激活

  • 计算 \(A = ReLU(Z)\)将负数置 0(形状 4×8)
    \(A = \begin{bmatrix} 0.155& 0.10& 0.23& 0.315& 0.355& \color{red}0& \color{red}0& 0.285\\ 0.18& 0.14& 0.24& 0.32& 0.41& \color{red}0& \color{red}0& 0.31\\ 0.14& 0.10& 0.08& 0.30& 0.42& \color{red}0& \color{red}0& 0.30\\ 0.19& 0.14& 0.17& 0.24& 0.40& 0.0& 0.08& 0.27 \end{bmatrix}\)

STEP 3 :第 2 次 线性变换

  • 计算 \(FFN\_Out = A · W2 + b2\)(形状 4×4)
    \(FFN\_Out = \begin{bmatrix} 0.193& 0.172& 0.2355& 0.056\\ 0.198& 0.195& 0.255& 0.062\\ 0.160& 0.182& 0.230& 0.020\\ 0.185& 0.199& 0.239& 0.033 \end{bmatrix}\)

子层 残差连接 + 层归一化(Add & Layer Norm)

子层 残差连接

  • 子层3的输入 Out2 与 前馈网络 FFN 输出 FFN_Out 相加
    • \(Sum3 = Out2 + FFN\_Out\)
  • 做 LayerNorm 得到 解码器第 1 次 的输出 Dec_Layer_Out_1(形状 4×4)
    \(Dec\_Layer\_Out\_\color{red}1 = \begin{bmatrix} 1.10& 0.70& -0.80& 1.40\\ 1.05& 0.85& -0.55& 1.25\\ 0.65& 1.15& -0.20& 1.00\\ 0.80& 1.05& -0.05& 0.90 \end{bmatrix}\)

解码器 Decoder 核心层 总结

  • 上述过程只是 第一次,原论文一共 重复6
  • 每一次包括:
    • 带掩码的多头注意力
    • 残差连接(相加)+ 层归一化
    • 交叉(多头)注意力
    • 残差连接(相加)+ 层归一化
    • 前馈网络(Feed-Forward Network,FFN)
    • 残差连接(相加)+ 层归一化
  • 上述 6 个步骤,重复 6 次,得到 解码器最终输出 Dec_Out
  • 形状依然是 4×4,本质上是 目标序列长度 L × 模型宽度 d_model
  • 得到的结果 Dec_Out,送入 线性层 + Softmax 层

线性层(Linear Layer)

  • 也叫 输出投影层(Output Projection Layer)
  • 每个位置d_model 维向量,映射到词汇表大小 Vocab_Size 维的空间
  • 得到未归一化的分数 Logits 矩阵,形状是 (序列长度 L,词汇表大小 V)
  • 哪一个位置的输出 分数越高,代表模型认为 词汇表 中该位置 对应那个词的概率越大
  • 例如
    • 举例中的英文词汇表是 {<START>:0, I:1, love:2, AI:3, <EOS>:4, <PAD>:5}Vocab_Size V=6

输入 Dec_Out

  • 输入:解码器最后一层(第6层)的输出 Dec_Out
  • 形状:(序列长度 L, d_model) = (4, 4)

线性层 转换过程(Linear Layer)

  • \(Logits = Dec\_Out · W\_out + b\_out\)
  • W_out(权重矩阵):形状必须是 (d_model, V),即 (4, 6)
  • b_out(偏置项):长度为 V,即 (6, )
  • 这些值在训练中是不断更新的,但在某次前向传播中就是固定的数值

W_out(权重矩阵)(4行 × 6列)

  • 原始 Transformer 实现中,W_out 直接复用 输出嵌入层(Output Embedding)的权重矩阵的转置
  • \(W_{out} = (W_{dec\_emb})^T\)
    • 大幅减少参数量(词汇表通常很大,如 V=30000,这个矩阵能省下几千万个参数)
    • 提升训练效果:让 理解词义(嵌入)和 生成词(输出)共享底层语义空间
      \(W_{out\_4×6} = \begin{bmatrix} 0.2& 0.8& 0.1& 0.3& 0.5& 0.0\\ 0.4& 0.2& 0.9& 0.1& 0.3& 0.6\\ 0.1& 0.3& 0.2& 0.7& 0.4& 0.5\\ 0.6& 0.1& 0.3& 0.2& 0.8& 0.4 \end{bmatrix}\)

b_out(偏置项)(长度为6的行向量,1 × 6)

  • \(b_{out\_1×6} = [\ 0.1\ \ \ \ 0.0\ \ \ \ 0.2\ \ \ \ 0.1\ \ \ \ 0.0\ \ \ \ 0.3\ ]\)

前面 解码器(6层)输出的 Dec_out 作为线性层的输入

每一行结果
Dec_Out [ 1.10, 0.70, -0.80, 1.40] # 位置0 (<START>)
[ 1.05, 0.85, -0.55, 1.25] # 位置1 (I)
[ 0.65, 1.15, -0.20, 1.00] # 位置2 (love)
[ 0.80, 1.05, -0.05, 0.90] # 位置3 (AI)

逐行计算 Logits[i] = Dec_Out[i] · W_out + b_out

  • 线性层的最终输出:Logits 矩阵(形状 4×6)
  • 对应 目标单词表,一般默认 <START> 开头
位置 <START> I love AI <EOS> <PAD> 用途说明
位置0 1.36 0.92 1.20 0.22 1.56 0.88 预测第1个词用
位置1 1.345 0.97 1.335 0.365 1.56 1.035 预测第2个词用
位置2 1.27 0.79 1.56 0.47 1.39 1.29 预测第3个词用
位置3 1.215 0.925 1.485 0.59 1.415 1.265 预测第4个词用

输出 Logits(分数)

  • 输出:Logits 分数矩阵
  • 形状:(序列长度 L, 词汇表大小 V) = (4, 6)
  • 解释:
    • 行:代表 4 个位置(<START>, I, love, AI)
    • 列:代表词汇表中的 6 个候选词

Softmax 层(分数 --> 概率)

  • 线性层输出的 Logits 是“未归一化的分数”,数值可正可负,范围不定
  • Softmax 的作用是
    • 将所有分数都变成正数(通过 \(e^x\) 指数函数)
    • 将它们压缩到 [0, 1] 区间,并且每一行的所有概率之和等于 1
    • 这样,我们就能直观地看出模型认为“当前位置最可能是哪个词”

输入

  • 上一步的 Logits 分数矩阵,形状 (4, 6)

计算公式

  • 对于一个位置(行)的 Logits 向量 \(z = [z_1, z_2, ..., z_6]\)
  • Softmax 计算第 j 个词的概率为:
    \(P(word_j) = \frac{e^{z_j}}{Σ(e^{z_k})}\),分母是对所有 k:1 --> 6 求和

Softmax 最终输出(概率矩阵 Probs,形状 4×6)

位置 <START> I love AI <EOS> <PAD> 总和
位置0 0.215 0.138 0.183 0.069 0.262 0.133 总和=1.0
位置1 0.199 0.137 0.197 0.075 0.247 0.146 总和=1.0
位置2 0.180 0.111 0.241 0.081 0.203 0.184 总和=1.0
位置3 0.170 0.127 0.223 0.091 0.208 0.179 总和=1.0
  • 根据这个概率矩阵,模型在每个位置“最想预测”(即概率最高)的词分别是:
位置 输入上下文(已看到的词) 概率最高的词(Argmax) 概率值 真实目标词 是否正确?
位置0 <START> <EOS> 0.262 I ❌ 错误
位置1 <START> I <EOS> 0.247 love ❌ 错误
位置2 <START> I love love 0.241 AI ❌ 错误
位置3 <START> I love AI love 0.223 <EOS> ❌ 错误

结果全部错误,因为上面的过程只是第一次训练

计算损失(Loss)—— 衡量模型预测有多“差”

  • 损失函数(交叉熵)会计算 模型预测的概率分布真实答案(One-hot 编码) 之间的差距

数学公式(交叉熵损失)

  • 对于 一个位置 i,如果真实词是 target,那么损失为:
  • \(Loss_i = -log( P_{model}(target) )\)
  • 整个批次的损失是所有位置损失的平均值

计算举例

位置 真实目标词 目标词索引 模型预测该词的概率 公式 该位置损失
位置0 I 1 0.138 -log(0.138) 1.981
位置1 love 2 0.197 -log(0.197) 1.624
位置2 AI 3 0.081 -log(0.081) 2.513
位置3 <EOS> 4 0.208 -log(0.208) 1.570

最终 Loss - 平均损失(该序列的):

  • Loss = (1.981 + 1.624 + 2.513 + 1.570) / 4 = 7.688 / 4 = 1.922
  • 解释:
    • 交叉熵损失的数值 > 0
    • 如果模型完美预测(概率 = 1.0),损失为 0
    • 这里计算得到损失是 1.922,说明模型 预测得还不够好,还需要继续训练

接下来的事:反向传播(Backpropagation)

计算梯度:

  • 从损失值出发,利用链式法则,一直往回计算每一个权重矩阵里每一个数值的 偏导数(梯度)
  • \(W_{emb}, W_Q, W_K, W_V, W_O, W1, W2, W_{out}\)

以权重矩阵 \(W_{out}\) 的第 1 个数 \(W_{out}[0,0]\) 为例

  • 线性层权重矩阵 \(W_{out}\) 中,第 0 行第 0 列的那个数
  • 前向传播时,这个值参与了位置0(<START>)对应 <START> 这个单词的 Logits 计算
  • 注意:我们预测的目标是 "I",但 W_out[0,0] 负责计算的是 Logits 矩阵里 第 0 列,即 这个词的得分
前向传播的数值(前面计算的结果)
  • 位置 0Dec_Out[0] 第一个数是 \(x_0 = 1.10\)
  • 我们的目标真实标签(Ground Truth)是 I,其 One-Hot 向量 y 为 [0, 1, 0, 0, 0, 0]
  • 位置 0 的最终概率分布 Probs[0][0.215, 0.138, 0.183, 0.069, 0.262, 0.133]
链式法则 :梯度"反向传播"的数学链
  • 损失 L 对权重 W_out[0,0] 的偏导数:\(\frac{∂L} {∂W_{out}[0,0]}\)

  • 前向传播时的链路是:

    • W_out[0,0] → Logit[0, 0] → Softmax → 损失 L
    • 其中,Logit[0, 0] 是 位置0 对 <START> 的分数
  • 链式法则 (反向传播)

    • 第 1 步:损失对 Logits 的梯度(反向起点) \(\frac{∂L} {∂Logits[0, j]} = Probs[0, j] - y[0, j]\)
    • 第 2 步:Logits 对权重的偏导数 \(\frac{∂Logits[0,0]} {∂W_{out}[0,0]} = Dec\_Out[0,0]\)
    • 第 3 步:把两个偏导数相乘(链式法则)\(\frac{∂L} {∂W_{out}[0,0]} = \frac{∂L} {∂Logits[0, j]} × \frac{∂Logits[0,0]} {∂W_{out}[0,0]}\)
  • 具体数值计算

    • 第 1 步:对于 j=0(即 <START> 列)
      • \(\frac{∂L} {∂Logits[0, j]} = Probs[0, j] - y[0, j] = 0.215 - 0 = 0.215\)
      • 作为对比,真实目标 j=1(I)的梯度是 0.138 - 1 = -0.862,负号 表示需要提高这个类的分数
    • 第 2 步:\(\frac{∂Logits[0,0]} {∂W_{out}[0,0]} = Dec\_Out[0,0] = 1.10\)
    • 第 3 步:\(\frac{∂L} {∂W_{out}[0,0]} = \frac{∂L} {∂Logits[0, j]} × \frac{∂Logits[0,0]} {∂W_{out}[0,0]} = 0.215 × 1.10 = 0.2365\)
  • 这个 0.2365 就是 W_out[0,0] 的最终梯度

  • 优化器(Optimizer)(如 Adam)会拿着这个 0.2365,学习率(比如 \(\color{red}-0.001\),去更新 W_out[0,0] 的原始数值

元素梯度 --> 矩阵梯度(梯度 回流 解码器Decoder)

  • 单个权重是这样算的,那么整个矩阵的梯度,就是把上述过程写成矩阵乘法的形式
1. 输出层(Linear Layer)的梯度
  • 损失对 Logits 的梯度:dL_dLogits = Probs - Y(形状 4×6,Y 是 One-Hot 矩阵)
  • 损失对偏置 b_out 的梯度(形状 6,):dL_db_out = sum(dL_dLogits, dim=0)(对位置维度求和)
  • 损失对权重 W_out 的梯度(形状 4×6):dL_dW_out = Dec_Out^T · dL_dLogits
  • 即 (4×4)^T · (4×6) = (4×6)。你看,这个矩阵乘法的结果形状和 W_out 完全一致。
2. 解码器 FFN(第二层 W2)的梯度
  • 设 A 是 ReLU 激活后的矩阵(形状 4×8),dL_dFFN_Out 是来自上一层的梯度。
  • dL_dW2 = A^T · dL_dFFN_Out(形状 8×4,与 W2 一致)
3. 解码器 FFN(第一层 W1)的梯度
  • 设 Z = Out2 · W1 + b1,A = ReLU(Z),dL_dA 是来自 W2 层的梯度。
  • 由于 ReLU 的导数很简单(输入大于0时为1,小于0时为0),我们在反向传播时会把 dL_dA 乘上一个掩码矩阵(Z > 0 的地方为1,其余为0)。
  • dL_dW1 = Out2^T · (dL_dA ⊙ ReLU_mask)(形状 4×8,与 W1 一致)
4. 解码器交叉注意力(Q、K、V 投影层)的梯度
  • 这是链式法则最长的部分。以 W_Q 为例,梯度必须穿过 Softmax、Scaling、MatMul 等环节。
  • 其核心矩阵形式为:dL_dW_Q = X^T · dL_dQ
  • 这里 X 是进入该子层的输入,dL_dQ 是从后面的 V 和注意力权重矩阵传播回来的梯度。
5. 解码器掩码自注意力(W_Q, W_K, W_V)的梯度
  • 和上面的交叉注意力公式完全一样,只是 X 来自解码器自身的偏移输入。
  • 唯一的区别是,在计算 dL_dScores 时,上三角掩码位置(-inf)的梯度会被强制设为 0,因为 -inf 在反向传播时没有贡献。
6. 输出嵌入层与输入嵌入层
  • 对于嵌入层(查表操作),梯度只更新那些被"查过"的行。
  • 输出嵌入层:dL_dW_dec_emb = One_Hot_Indices^T · dL_dY(由于权重共享,这个梯度会同时累加到最后的 W_out 上)

梯度 回流 编码器 Encoder

通过"交叉注意力"(Cross-Attention)和"残差连接" 回流 编码器 Encoder
1. 通过交叉注意力回溯:
  • 在解码器的交叉注意力层,梯度 dL_dQ 会沿着 Q 往回传,但更重要的是,梯度也会流经 K 和 V。因为 K 和 V 的来源是编码器的最终输出 Enc_Out。
  • 当梯度流到 K 和 V 时,它们会汇聚成 dL_dEnc_Out。
  • 这个 dL_dEnc_Out 会从解码器"跨"回到编码器,成为编码器输出端的梯度。
2. 通过残差连接加速:
  • 残差连接(Add)在反向传播时相当于一个"梯度高速公路",它将解码器传来的梯度不加衰减地直接复制一份,跳过自注意力层和 FFN 层,直通编码器的底部。
3. 编码器自爱:
  • 当 dL_dEnc_Out 进入编码器的最后一层后,它就像在多层的解码器中一样,一层层地穿过 FFN、Add & Norm、Multi-Head Self-Attention,最终抵达编码器的嵌入层 W_enc_emb,并更新其中的权重。

更新权重:

  • 优化器(Optimizer)(如 Adam)拿着这些梯度,乘以学习率,去更新所有的权重矩阵
  • 让模型在下一次前向传播时,对这些句子的预测损失变得更小

重复迭代:

  • 处理下一个 Batch 的句子对,重复上述所有步骤
  • 编码器 → 解码器 → 输出 → 损失 → 反向传播
  • 直到模型在整个数据集上的 损失收敛

解码器 Decoder 最终输出:概率矩阵 Probs

posted on 2026-06-17 14:44  中年二班  阅读(6)  评论(0)    收藏  举报