Transformer模型解码器输入输出逻辑与训练推理疑问
Transformer解码器核心逻辑答疑

训练阶段已知y_true,为什么还要输入解码器算输出概率?
训练阶段给解码器喂真实标签的机制叫Teacher Forcing,根本不是什么“直接抄答案”:
- 首先是为了训练稳定好收敛:如果一开始训就像推理那样拿模型自己瞎猜的结果当下文输入,参数刚初始化的时候模型输出全是乱的,错误会沿着序列一路传下去,模型可能训半天都摸不到规律,直接训崩。直接给每个位置喂它之前所有位置的真实标签,相当于给模型搭了个扶手,让它不用纠结前面的内容对不对,专心学“给定正确上文+源序列编码结果,当前位置该出什么token”的映射就行,收敛速度快很多。
- 其次算输出概率是训练的必要步骤:模型训练的目标就是让真实标签对应的预测概率尽可能高,其他错词的概率尽可能低。你不跑前向传播算出每个位置在整个词表上的概率分布,就没法和真实标签算交叉熵损失,更没法反向传播更新参数——真要是输入y_true就直接输出y_true,那模型啥都学不会,和一个复制粘贴的脚本没区别。
这里要注意:喂给解码器的y_true会提前做右移,还会加因果掩码,模型预测第i个位置的时候,完全看不到i位置及之后的真实标签,根本没机会作弊。
Output Embedding和Output Probabilities模块有什么关联?
这俩模块在原论文里是权重共享的,自己写代码实现的时候根本不用给Output Probabilities单独初始化一套权重:
- Output Embedding的作用是把输入解码器的token id转成固定维度的稠密向量,权重矩阵形状是
[词表大小, 模型隐层维度]。 - Output Probabilities模块要做的事,是把解码器最后一层输出的隐层维度向量,映射成和词表长度一致的分数,再过softmax得到每个词的生成概率。这一步用到的映射权重,直接把Output Embedding的权重拿过来转置一下,变成
[模型隐层维度, 词表大小]就能用。
这么做一是能砍一大块可训练参数量,省显存;二是能让输入侧的词嵌入语义空间和输出侧的预测语义空间对齐,收敛更快,生成效果也会好一点。
推理阶段没有y_true,是不是要循环把预测的y_pred喂回解码器?
没错,这就是解码器自回归生成的核心逻辑,和训练阶段能并行算所有位置的输出不一样,推理是逐位串行生成的:
- 第一步解码器只有一个起始特殊token(比如
<s>)当输入,结合编码器输出的源序列编码结果,算出第一个位置的词概率分布,按你选的策略(贪心取最高概率、beam search、随机采样都行)选出第一个生成的token。 - 后面每一步,都把之前已经生成的所有token拼成完整序列喂给解码器,预测下一个位置的token。工程实现上一般会加KV缓存,把之前算过的注意力键值对存下来,不用每一步都把所有历史token重新算一遍注意力,能快不少,但核心逻辑没变。
- 一直重复这个过程,直到模型输出结束特殊token(比如
<eos>),或者达到你提前设好的最大生成长度,就停手输出结果。
别觉得这种串行方式笨,现在所有的大模型推理优化,本质都是在这个逻辑基础上省冗余计算,绕不开逐位生成的本质——毕竟人说话写文章也是一个字一个字往外蹦,不可能同时把一整段所有位置的内容都同时想出来。
内容的提问来源于stack exchange,提问作者Paul726
相关产品推荐
相关产品推荐

