举例子讲解Transformer Decoder层流程

182 阅读5分钟

​专注讲解一个完整的、独立的Decoder架构​​(比如在GPT这类纯Decoder模型中)。这次用最直白的语言和具体数字例子,追踪一个词向量从输入到输出的全过程。

​任务:​​ 用Decoder生成句子 ​​"我很开心"​​,我们观察它如何生成 ​​"开心"​​ 这个词。

​模型极简参数(便于理解):​

  • d_model(向量维度)= ​​3​​ (实际中512+,这里用3维可视化)
  • d_ff (FFN内部维度) = ​​6​​ (升维2倍)
  • ​词表:​[<SOS>, 我, 很, 开心, <EOS>, ...] (假设词表大小=5)
  • ​已生成序列:​["<SOS>", "我", "很"](接下来要生成“开心”)

🔍 图解Decoder单层处理流程(生成“开心”的位置)

我们聚焦Decoder的​​某一层​​(比如第1层),看看它对​​当前要生成的位置​​(“开心”的位置,即序列第3位)做了什么。

📍 阶段0:输入准备

  1. ​输入序列:​["<SOS>", "我", "很"] (位置0, 1, 2)

  2. ​目标输入:​​ 模型当前要处理 ​​位置3​​ (即将生成"开心"的位置)。

  3. ​该位置的输入向量 (input_pos3):​

    • ​位置嵌入:​​ 因为位置3还没生成词,输入是<空位>

    • ​操作:​​ 使用 <SOS>Padding 的嵌入 + ​​位置编码 (Position 3)​​。简单起见,我们假设初始输入为:

      • input_pos3 = [0.1, 0.2, 0.3] (维度=3,代表“待生成位置3”的状态)

🚧 阶段1:Masked Multi-Head Self-Attention (只关注已知词!)

  • ​目的:​​ 让位置3 (待生成) 关注​​前面已生成的词​​ (<SOS>, , ),​​但不能看自己或未来!​

  • ​输入:​​ 所有位置0,1,2,3的向量(形状 [4, 3])。位置3的输入是 [0.1, 0.2, 0.3]

  • ​关键 - Masking:​

    • 位置3 (待生成) ​​只能关注​​ 位置0 (<SOS>)、位置1 ()、位置2 ()。
    • ​位置3自己和位置4(未来)的注意力权重被强制设为极小值(如-999)!​
  • ​计算 (简化):​

    1. 位置3会计算和 <SOS> 的相似度。

    2. 假设注意力权重分布:

      • 关注 <SOS> 权重 = 0.1
      • 关注 权重 = 0.3
      • 关注 权重 = ​​0.6​​ (“很”是刚生成的词,最相关)
    3. 加权求和 (output_self_pos3):

      output_self_pos3 = 0.1 * <SOS>向量 + 0.3 * "我"向量 + 0.6 * "很"向量
      

      假设计算结果是: [0.8, 1.2, 0.4] (形状 [1, 3])

  • ​作用:​​ 位置3知道了:“我”是主语,“很”是一个程度副词(修饰后面内容),我需要生成一个形容词。

  • ​输出 (output_self_pos3):​[0.8, 1.2, 0.4]

🔄 阶段2:Add & Norm 1

  • ​操作:​

    • 残差连接 = output_self_pos3 + input_pos3 = [0.8+0.1, 1.2+0.2, 0.4+0.3] = [0.9, 1.4, 0.7]

    • 层归一化 (LayerNorm):对 [0.9, 1.4, 0.7] 进行标准化(使其均值为0,方差为1)。

      • 简化假设归一化后: [0.0, 1.0, -0.5] (形状 [1, 3])
  • ​输出 (norm_out1_pos3):​[0.0, 1.0, -0.5] (稳定后的信息)

🧠 阶段3:Position-wise Feed-Forward Network (FFN) - 特征放大器

  • ​输入 (norm_out1_pos3):​[0.0, 1.0, -0.5] (代表:“程度副词后需要一个正面形容词”)

  • ​FFN内部操作:​

    1. ​升维映射:​hidden = [0.0, 1.0, -0.5] * W₁ + b₁

      • W₁ 形状 [3, 6]b₁ 形状 [1, 6]
      • 假设结果: hidden = [0.5, -0.2, 1.8, 0.1, -1.0, 0.9](升维到6,可能捕获“正面情绪”、“形容词类”等特征)
    2. ​ReLU激活:​relu_hidden = max(0, hidden) = [0.5, 0, 1.8, 0.1, 0, 0.9] (过滤掉负值)

    3. ​降维映射:​ffn_output = relu_hidden * W₂ + b₂

      • W₂ 形状 [6, 3]b₂ 形状 [1, 3]
      • 假设计算结果: ffn_output = [1.5, 0.2, 2.0](维度压缩回3)
  • ​作用:​​ 将“程度副词后接形容词”的提示,​​深度加工​​为“需要生成一个强烈的正面情绪形容词”!

  • ​输出 (ffn_output_pos3):​[1.5, 0.2, 2.0](维度 [1, 3]

🔄 阶段4:Add & Norm 2

  • ​操作:​

    • 残差连接 = ffn_output_pos3 + norm_out1_pos3 = [1.5+0.0, 0.2+1.0, 2.0+(-0.5)] = [1.5, 1.2, 1.5]
    • 层归一化 (LayerNorm): 简化假设归一化后: [0.8, 0.1, 1.5] (形状 [1, 3])
  • ​输出 (layer_output_pos3):​[0.8, 0.1, 1.5](该Decoder层对位置3的最终输出)

  • ​注意:​​ 这个输出会传递给下一层Decoder(如果有多层),或者直接用于预测。

🔮 阶段5:输出预测(在最终Decoder层之后)

  1. ​最终输入:​​ 假设是顶层Decoder对位置3的输出 (final_vector) = [0.8, 0.1, 1.5] (形状 [1, 3])

  2. ​线性层:​logits = final_vector * W_vocab + b_vocab

    • W_vocab 形状 [3, 5](因为词表大小=5),b_vocab 形状 [1, 5]

    • 假设计算结果: logits = [ -0.2, 1.0, 0.5, 3.0, -1.0 ]

      • 对应词表: [0: <SOS>, 1: 我, 2: 很, 3: 开心, 4: <EOS>]
  3. ​Softmax:​​ 将 logits 转成概率:

    • probs = softmax([ -0.2, 1.0, 0.5, 3.0, -1.0 ])

    • 假设结果: [0.05, 0.15, 0.10, 0.65, 0.05]

      • 开心 的概率 (index=3) = ​​0.65​​ (最高!)
      • = 0.15, = 0.10,<SOS>/<EOS> ≈ 0.05
  4. ​预测输出:​​ 选择概率最高的词 -> ​​“开心”​​!生成成功!


🧩 核心总结:纯Decoder如何生成一个词(位置3“开心”)

阶段输入向量(位置3)处理内容输出向量(位置3)代表的意义 (简化)
​0. 输入准备​[0.1, 0.2, 0.3]位置3的初始状态-"开始生成位置3啦!"
​1. Masked Self-Attn​[0.1, 0.2, 0.3]​只关注前面已生成的词(<SOS>, , )​​,得知:后面接形容词![0.8, 1.2, 0.4]"前面有‘我’和‘很’,我要生成形容词!"
​2. Add & Norm 1​[0.8, 1.2, 0.4]稳定信息,保留初始状态[0.0, 1.0, -0.5]"初步整理:程度副词后需要形容词!"
​3. FFN​[0.0, 1.0, -0.5]​深度加工:升维→激活→降维​​,提炼核心语义[1.5, 0.2, 2.0]"强烈!需要生成一个表示正面情绪、状态良好的形容词!"
​4. Add & Norm 2​[1.5, 0.2, 2.0]再次稳定信息[0.8, 0.1, 1.5]"最终结论:生成一个表示开心的词!"
​5. 输出层​[0.8, 0.1, 1.5](顶层的)线性层Softmaxprobs = [..., **0.65**]​“开心”概率最高!它被选中了!​

✅ 关键为什么需要这些?

  1. ​Masked Self-Attention:​

    • ​目的:​​ 让模型生成每个词时​​只依赖已经生成的词​​(符合语言规律)。
    • ​就像说话:​​ 你只能说已经出口的词语,不能说后面还没想到的词。​​掩码​​保证了这个规则!
  2. ​FFN (前馈神经网络):​

    • ​目的:​​ 将注意力层捕获的上下文信息(这里是“我很__”)​​做深度加工、提炼、增强​​。它是​​特征提取和语义深化的核心引擎​​。
    • ​就像思考:​​ 注意力告诉你“需要形容词”,FFN 帮你深入想“需要什么样的形容词”(正面?强烈?表情绪?)。
  3. ​Add & Norm (残差连接+层归一化):​

    • ​目的:​​ 稳定训练过程,避免信息在网络传递中衰减或爆炸,让模型更容易学。
  4. ​输出层:​

    • ​目的:​​ 把Decoder最后一层输出的隐藏状态(一个高维向量)​​转换回词表空间​​,告诉我们模型最想生成哪个词。

​简单来说,Decoder的工作流就是:​

  1. ​看前面说了什么(Masked Self-Attn)​
  2. ​深入思考要说什么(FFN)​
  3. ​预测出下一个词(Output Layer)​

​不断重复这个过程,直到生成完整的句子或遇到结束符。​

希望这个剥离Encoder、专注于Decoder自身工作流、使用直观数值的详解,能让你彻底明白它是如何运作的!