问题与目标
序列到序列任务的输入和输出长度都可能变化,例如翻译、摘要和问答。经典 Seq2Seq 使用编码器把输入压缩成状态,再由解码器逐步生成输出。当所有输入信息都挤进一个固定向量时,长序列中的细节容易丢失。
上一阶段已经解释 RNN、LSTM 和 Attention 的基本动机。本篇不重复网络内部公式,而是把它们放入文本生成流程,说明 Teacher Forcing、自回归推理和动态上下文之间的关系。

固定上下文让每个解码步骤读取同一个压缩结果;Attention 则根据当前解码状态重新计算权重,让不同输出位置关注不同输入 Token。
核心概念
编码器和解码器
编码器读取输入序列并产生隐藏状态。最早的 Seq2Seq 只把最后一个隐藏状态交给解码器;改进后会保留所有编码器状态,让解码器通过 Attention 动态聚合。
解码器每一步接收:
- 上一步输出 Token 的向量;
- 上一步解码状态;
- 当前 Attention 得到的上下文向量。
输出层把解码状态映射到词表大小的 logits,再选择下一个 Token。
Teacher Forcing 与自回归推理
训练时通常知道标准答案,可以把真实的前一个 Token 输入解码器,这叫 Teacher Forcing。它可以加快训练,但也造成训练与推理不一致:推理时没有标准答案,只能把模型自己生成的 Token 送回下一步。一旦前面生成错误,后续输入也会偏离。
训练输入:<bos> 检查 网络
训练目标:检查 网络 状态
推理过程:<bos> → 模型预测 → 再把预测送回模型 → ...
Attention 的三个角色
- Query:当前解码器需要寻找什么信息。
- Key:每个输入位置提供的匹配线索。
- Value:匹配后真正参与聚合的内容。
权重由 Query 与各 Key 的相关性计算,再经过 Softmax 归一化。上下文向量是 Value 的加权和,因此它会随解码步骤变化。
可运行实现
下面用 NumPy 演示两个解码步骤如何得到不同 Attention 权重。数组是自创数值,只验证计算关系,不代表训练完成的语言模型。
import numpy as np
def softmax(values: np.ndarray) -> np.ndarray:
shifted = values - values.max()
exp = np.exp(shifted)
return exp / exp.sum()
def attend(query: np.ndarray, encoder_states: np.ndarray):
scores = encoder_states @ query
weights = softmax(scores)
context = weights @ encoder_states
return weights, context
tokens = ["检查", "节点", "网络", "状态"]
encoder_states = np.array([
[0.9, 0.1, 0.0],
[0.2, 0.8, 0.1],
[0.1, 0.3, 0.9],
[0.3, 0.7, 0.5],
])
queries = {
"生成主体": np.array([0.2, 1.0, 0.1]),
"生成对象": np.array([0.1, 0.2, 1.0]),
}
fixed_context = encoder_states.mean(axis=0)
print("固定上下文:", np.round(fixed_context, 3))
for step, query in queries.items():
weights, context = attend(query, encoder_states)
print(f"\n{step}")
print(dict(zip(tokens, np.round(weights, 3))))
print("动态上下文:", np.round(context, 3))
第一条 Query 更接近“节点”的状态,第二条 Query 更接近“网络”的状态,因此两次权重和上下文向量不同。实际模型中的 Query、Key、Value 都由训练得到的矩阵投影产生。
Teacher Forcing 的数据位移可以直接观察:
target = ["<bos>", "check", "network", "<eos>"]
decoder_input = target[:-1]
expected_output = target[1:]
print(decoder_input) # ['<bos>', 'check', 'network']
print(expected_output) # ['check', 'network', '<eos>']
常见问题与排查
Attention 权重能否直接当作解释
权重能显示某层某头的聚合比例,但不等于完整因果解释。模型还包含多层变换、残差和多个注意力头,不能仅凭一张热力图断言模型“因为某个词”做出决定。
训练损失下降,推理结果仍然很差
检查训练与推理的输入是否一致、<bos> 和 <eos> 是否正确、是否一直使用 Teacher Forcing,以及推理循环是否把上一步输出送入下一步。
输出永远不结束
模型可能没有学会 <eos>,或者推理代码没有检查停止符。还应设置最大生成长度,避免异常输出形成无限循环。
长序列仍然消耗很大
Attention 改善了固定向量的信息瓶颈,但标准自注意力的计算和显存开销会随序列长度快速增长。解决信息访问问题并不等于解决全部效率问题。
小结
Seq2Seq 建立了可变长度输入到可变长度输出的框架,Attention 让解码器不必把全部信息压缩在一个固定状态中。理解动态上下文、Teacher Forcing 和自回归推理后,Transformer 的编码器—解码器结构就有了清晰来源。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


