前言
Hello,大家好,我是
GISer Liu
😁,一名热爱AI技术的GIS开发者,本系列文章是作者参加DataWhale2025年1月份学习赛,旨在讲解Transformer模型的理论和实践。😲
🙂本文将从Decoder (解码器)的角度出发,深入解析Transformer模型在生成任务中的核心机制。我们将重点探讨Decoder的结构设计、信息传递机制以及其在序列生成任务中的关键作用。通过详细分析Decoder的掩码机制(Masking) 、填充机制(Padding) 、多头自注意力机制(Masked Multi-Head Attention)以及输出生成过程,帮助读者全面理解Decoder如何逐步生成输出序列。此外,本文还将对比Decoder与Encoder(编码器)在任务目标、注意力机制和训练策略上的差异,并结合实际案例和生活中的类比,帮助读者更好地掌握Decoder的工作原理及其应用。
一、解码器(Decoder)
1. Decoder解码流程
① 输出嵌入(Output Embedding)的右向偏移
在解码器中,输入嵌入(Input Embedding)是指解码器接收的输入序列的嵌入表示。为了确保解码器在生成每个符号时能够正确地获取之前生成符号的上下文信息,模型会对输入嵌入进行向右偏移一个位置。具体来说,这意味着在训练阶段,解码器的输入序列会被向右移动一个位置,使得每个符号在生成时只能看到它之前的符号。
为什么需要偏移?
- 防止信息泄露:如果不进行偏移,解码器在生成当前符号时可能会"看到"未来的符号,这会导致模型在训练时作弊,提前知道未来的信息。
- 保持因果性:解码器生成符号的过程是逐步进行的,每个符号的生成都依赖于之前生成的符号。偏移确保了这种因果性。
技术实现:
- 偏移是通过将输入序列向右移动一个位置来实现的。例如,如果输入序列是
[A, B, C]
,那么偏移后的序列将是[PAD, A, B]
,其中PAD
是一个填充符号。
辅助理解:
- 假设你正在按照食谱烹饪一道菜,食谱的步骤是:1. 切菜 → 2. 炒菜 → 3. 调味 → 4. 装盘。
- 在烹饪过程中,你不能提前知道下一步是什么。比如,当你正在切菜时,你不能提前知道调味的步骤,否则你可能会在切菜时就开始准备调味料,这会导致混乱。
解码器中的实现:
- 解码器在生成每个符号时,只能看到它之前生成的符号。为了实现这一点,解码器的输入序列会向右偏移一个位置。例如,如果输入序列是
<font style="color:rgb(64, 64, 64);">[切菜, 炒菜, 调味]</font>
,那么偏移后的序列将是<font style="color:rgb(64, 64, 64);">[PAD, 切菜, 炒菜]</font>
,其中<font style="color:rgb(64, 64, 64);">PAD</font>
是一个填充符号。为什么需要偏移?
- 偏移确保了生成过程的因果性,防止模型在生成当前符号时"偷看"未来的符号。
② 位置编码的整合
位置编码(Positional Encoding)用于为序列中的每个符号提供位置信息。在解码器中,位置编码与输出嵌入相结合,以保留符号的序列顺序信息。
结合方式:
- 位置编码和输出嵌入通常通过相加的方式进行结合。假设输出嵌入为
E
,位置编码为P
,则结合后的表示为E + P
。
为什么需要位置编码?
- Transformer模型本身没有显式的序列顺序信息,位置编码的引入使得模型能够区分不同位置的符号。
辅助理解:
- 在烹饪时,每个步骤的顺序非常重要。比如,你不能在炒菜之前就调味,否则味道会不均匀。
- 为了记住每个步骤的顺序,你可能会在食谱上标注步骤的编号(如步骤1、步骤2等)。
解码器中的实现:
- 解码器通过位置编码为每个符号提供位置信息。位置编码和输出嵌入通过相加的方式结合,例如:
<font style="color:rgb(64, 64, 64);">输出嵌入 + 位置编码</font>
。为什么需要位置编码?
- Transformer模型本身没有显式的序列顺序信息,位置编码的引入使得模型能够区分不同位置的符号。
③ 带掩码的多头自注意力机制
解码器使用带掩码的多头自注意力机制(Masked Multi-Head Attention),以确保在生成每个符号时,模型只能看到它之前的符号,而不能看到未来的符号。
掩码的作用:
- 掩码是一个矩阵,用于屏蔽未来符号的注意力权重。具体来说,掩码矩阵的上三角部分(包括对角线)被设置为负无穷大,这样在计算注意力权重时,未来符号的权重会被忽略。
为什么需要掩码?
- 防止模型在生成当前符号时"偷看"未来的符号,确保生成过程的因果性。
辅助理解:
- 假设你在烹饪时,食谱的每一步都写在一张卡片上,卡片叠在一起。你只能看到当前卡片和之前的卡片,而不能看到未来的卡片。
- 例如,当你正在炒菜时,你只能参考切菜的步骤,而不能提前看到调味的步骤。
解码器中的实现:
- 解码器使用带掩码的多头自注意力机制,确保在生成每个符号时,模型只能看到它之前的符号。掩码矩阵的上三角部分(包括对角线)被设置为负无穷大,这样在计算注意力权重时,未来符号的权重会被忽略。
④ 编码器-解码器注意力交互
解码器不仅使用自注意力机制,还引入了编码器-解码器注意力交互(Encoder-Decoder Attention)。这使得解码器能够聚焦于输入序列的重要部分,从而生成受输入语境影响的输出符号。
技术实现:
- 在编码器-解码器注意力中,解码器的输出作为查询(Query),编码器的输出作为键(Key)和值(Value)。通过这种方式,解码器能够根据输入序列的信息生成输出。
辅助理解:
- 假设你正在烹饪一道菜,但你不太确定某个步骤的具体操作(比如如何调味)。这时,你可以参考食谱的详细说明(编码器的输出),来调整你的操作。
- 例如,食谱可能会告诉你:"在炒菜时加入适量的盐和酱油",你可以根据这个提示来调整调味的步骤。
解码器中的实现:
- 解码器不仅使用自注意力机制,还引入了编码器-解码器注意力交互。解码器的输出作为查询(Query),编码器的输出作为键(Key)和值(Value)。通过这种方式,解码器能够根据输入序列的信息生成输出。
为什么需要编码器-解码器注意力?
- 这使得解码器能够聚焦于输入序列的重要部分,从而生成受输入语境影响的输出符号。
⑤ 基于位置的前馈网络
在自注意力层之后,解码器对每个符号独立施加位置编码的前馈网络(Position-wise Feed-Forward Network)。该网络旨在捕捉输入和已生成符号之间的复杂模式与关联,以助力精确输出序列的构建。
技术实现:
- 前馈网络通常由两个全连接层组成,中间使用ReLU激活函数。每个符号的前馈网络是独立计算的,这使得模型能够捕捉到符号之间的复杂关系。
辅助理解:
- 在烹饪时,每个步骤的操作都是独立的,但它们之间又存在复杂的关联。例如,切菜的大小会影响炒菜的时间,而炒菜的时间又会影响调味的效果。
- 为了捕捉这些复杂的关联,你需要在每个步骤中仔细调整操作。
解码器中的实现:
- 在自注意力层之后,解码器对每个符号独立施加位置编码的前馈网络。该网络旨在捕捉输入和已生成符号之间的复杂模式与关联。
2. Decoder的子结构
Decoder部分相比于Encoder,其结构中增加了一个名为"Mask"的多头注意力子层。与标准多头注意力机制中的缩放点积注意力不同,Masked Multi-Head Attention在应用缩放操作之后引入了一个Mask步骤,用于实现因果性约束,防止未来信息泄露。
解码流程:
- 输入序列嵌入:假设当前已经解码的序列为 s1,s2,...,st−1s_1, s_2, ..., s_{t-1},将该序列进行词向量和位置向量嵌入,生成输入嵌入表示。
- Masked Multi-Head Attention:对上述嵌入向量进行带掩码的多头自注意力计算,确保解码器当前生成的词仅依赖于先前已生成的词,避免未来信息泄露。
- Encoder-Decoder Attention:将编码器的输出作为键(Key)和值(Value),结合解码器的中间表示作为查询(Query),进行多头注意力计算,从而将编码器的上下文信息融入解码器。
- 前馈网络(Feed Forward Network):对每个位置上的表示独立施加前馈网络(两层全连接网络加激活函数),提升网络的非线性建模能力。
- 重复解码:上述步骤会重复执行 NN 次,直到生成完整的输出序列。
- 输出层:通过线性变换和Softmax层,得到目标词汇的概率分布,用于预测下一步的输出。
整理下解码器的基本结构:
子结构 | 功能 | 组成 |
---|---|---|
子结构-1 | 带掩码的多头自注意力机制 | 防止信息泄露,确保生成过程的因果性 |
子结构-2 | 编码器-解码器多头注意力机制 | 在编码器的输出和解码器的中间表示之间建立联系 |
子结构-3 | 前馈网络 | 提升非线性建模能力,作用于每个符号位置 |
子结构-4 | 线性层和Softmax层 | 预测目标词汇的概率分布,用于生成下一步的输出 |
3. Decoder的多头自注意力与Encoder的多头自注意力的区别
① 编码器的多头自注意力
- 任务:编码器的任务是提取输入序列的全局特征,不受因果顺序的限制,因此不需要遮掩机制。
- 结构:编码器的多头自注意力仅依赖于输入序列的信息,不涉及其他模块。
② 解码器的多头自注意力
- 任务:解码器的任务是预测输出序列的下一个词。这要求它根据已生成的序列部分预测未来词,同时避免泄露未来信息。
- 结构:解码器的多头自注意力除了包含自注意力层外,还额外包含一个交叉注意力层,允许解码器访问编码器编码的输入序列的隐藏表示。
③ 掩码机制(Masking)
- 编码器:编码器没有掩码机制,可以自由处理和理解整个输入序列。
- 解码器:解码器的自注意力采用因果掩码机制,确保在生成输出序列时,当前词只能与之前的词进行交互,避免未来信息泄露。
④ 模型结构差异
- 编码器:编码器的多头自注意力仅依赖于输入序列的信息,不涉及其他模块。
- 解码器:解码器的多头自注意力除了包含自注意力层外,还包括交叉注意力层,允许解码器访问编码器编码的输入序列的隐藏表示。
⑤ 训练与生成过程的差异
- 编码器:在训练和推理阶段,编码器的自注意力处理方式相同,因为它总是可以访问整个输入序列。
- 解码器 :
- 在训练阶段,解码器可以并行处理整个目标序列;
- 在推理阶段,目标序列是逐步生成的,解码器必须依次计算每个新词的注意力。
上图中,每一部分的功能如下:
- Masked Multi-Head Attention :
- 输入:当前解码器嵌入序列,应用掩码防止未来信息泄露。
- 目标:确保生成因果性。
- Encoder-Decoder Attention :
- 输入:编码器输出作为Key和Value,Masked Multi-Head Attention结果作为Query。
- 目标:通过对齐编码器隐藏表示与解码器隐藏状态实现信息交互。
- Add & Norm :
- 功能:残差连接后进行归一化,防止梯度消失。
- Feed Forward :
- 功能:提高网络建模能力,作用于每个位置。
- Softmax :
- 功能:生成输出词汇的概率分布,用于预测。
二、掩码(Mask)详解
掩码(Mask)是Transformer模型中非常重要的机制,尤其是在解码器(Decoder)中。它的主要作用是控制模型在生成序列时的信息流动,确保模型不会"偷看"未来的信息。
1. Decoder为什么要加Mask?
掩码的作用:
- 因果关系(Causality):确保当前位置的输出仅仅依赖于之前的位置,而不是未来的位置。
- 训练与推理的一致性:在训练时,模型可以一次性看到整个目标序列,但在推理时,模型只能逐步生成序列。掩码确保了训练和推理时的一致性。
- 避免信息泄露:防止模型在生成当前符号时"偷看"未来的符号,确保生成过程的因果性。
生活中的例子:
- 假设你正在写一篇作文,作文的每个句子都是按顺序生成的。你不能提前知道后面的句子是什么,否则你可能会根据后面的内容来调整当前的句子,这会导致逻辑混乱或不连贯。。
技术实现:
- 掩码通常是一个上三角矩阵,其中上三角部分(包括对角线)设为0,其余部分设为负无穷大。在计算注意力权重时,掩码会被加到注意力分数上。这样,上三角部分的分数在softmax后会变成0,从而屏蔽了未来的信息。
2. 填充(Padding)机制和掩码(Masking)机制详解
假设我们正在处理一个机器翻译任务,将英文句子翻译成中文。在这个任务中,输入序列(英文句子)和输出序列(中文句子)的长度可能不一致,因此需要使用填充机制和掩码机制来处理这些序列。
① 填充(Padding)机制
(1) 为什么需要填充?
- 在训练时,输入序列的长度可能不一致。例如,一个批次中的句子长度可能从 5 个 token 到 15 个 token 不等。
- 为了将这些序列统一为相同的长度,通常会在较短的序列后面添加特殊的填充 token(例如
<PAD>
)。
(2) 填充的实现
- 假设训练集中最长的句子长度为 10 个 token,我们有以下两个句子:
- 英文句子 :
"I love cats"
→["I", "love", "cats", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
- 中文句子 :
"我喜欢猫"
→["我", "喜", "欢", "猫", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
- 英文句子 :
- 填充后的序列长度统一为 10 个 token,较短的句子用
<PAD>
填充。
2. 掩码(Masking)机制
(1) 为什么需要掩码?
- 填充 token 是无效的,模型在计算注意力权重时应该忽略这些 token。
- 掩码的作用是告诉模型哪些位置是真实的 token,哪些位置是填充的 token。
(2) 掩码的实现
- 掩码矩阵与输入序列的长度相同,真实 token 的位置用
0
表示,填充 token 的位置用1
表示。 - 对于上述两个句子,对应的掩码矩阵为:
- 英文句子 :
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
- 中文句子 :
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
- 英文句子 :
(3) 掩码的应用
- 在计算注意力权重时,掩码为
1
的位置会加上一个非常大的负数(例如负无穷),这样在经过 softmax 操作后,这些位置的值将接近 0,从而不会对全局概率预测产生影响。
3. 详细案例
(1) 输入序列
- 假设我们有以下两个英文句子:
"I love cats"
→["I", "love", "cats", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
"She enjoys reading"
→["She", "enjoys", "reading", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
- 对应的中文翻译:
"我喜欢猫"
→["我", "喜", "欢", "猫", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
"她喜欢阅读"
→["她", "喜", "欢", "阅", "读", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
(2) 填充后的序列
- 英文句子:
["I", "love", "cats", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
["She", "enjoys", "reading", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
- 中文句子:
["我", "喜", "欢", "猫", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
["她", "喜", "欢", "阅", "读", <PAD>, <PAD>, <PAD>, <PAD>, <PAD>]
(3) 掩码矩阵
- 英文句子:
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
- 中文句子:
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
(4) 掩码的应用
- 在计算注意力权重时,掩码为
1
的位置会加上一个非常大的负数(例如负无穷),这样在经过 softmax 操作后,这些位置的值将接近 0,从而不会对全局概率预测产生影响。
4. 技术实现细节
(1) 掩码矩阵的生成
- 掩码矩阵的形状与输入序列的形状相同。
- 对于每个序列,生成一个掩码向量,其中真实 token 的位置为
0
,填充 token 的位置为1
。
(2) 掩码的应用
- 在计算注意力分数时,将掩码矩阵加到注意力分数上:
python
attention_scores = query @ key.transpose(-2, -1) # 计算注意力分数
attention_scores = attention_scores + mask * -1e9 # 加上掩码
attention_weights = softmax(attention_scores) # 计算注意力权重
- 掩码为
1
的位置会被加上负无穷,经过 softmax 后,这些位置的权重接近 0。
(3) 整理结果
整理一下结果:
机制 | 目的 | 实现方式 | 作用 |
---|---|---|---|
填充机制 | 统一输入序列的长度 | 在较短的序列后面添加填充 token(例如 <PAD> ) |
使所有序列的长度一致,便于批量处理 |
掩码机制 | 屏蔽填充 token 的影响 | 生成掩码矩阵,真实 token 为 0 ,填充 token 为 1 |
在计算注意力权重时忽略填充部分 |
掩码应用 | 防止填充 token 影响模型的计算 | 将掩码为 1 的位置加上负无穷,经过 softmax 后权重接近 0 |
确保模型只关注真实的 token,忽略填充部分 |
- 填充机制 和掩码机制是 Transformer 模型中处理变长序列的重要技术。
- 填充机制通过添加填充 token 统一序列长度,掩码机制通过屏蔽填充 token 确保模型只关注真实的 token。
- 在实际应用中,填充机制和掩码机制通常结合使用,以确保模型能够正确处理变长序列。
3. Mask-Multi-Head-Attention
理解了填充和掩码的机制,我们下面的结果就很好理解了:
Mask的作用:
- 防止Decoder"seeing the future",就像防止考生偷看考试答案一样。
技术实现:
- 掩码是一个下三角矩阵,对角线及左下部分为1,其余部分为0。例如,一个10维度的下三角矩阵如下:
python
tensor([[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]], dtype=torch.uint8)
为什么可以防止Decoder"偷看"?
- 在计算注意力权重时,掩码为0的位置会加上一个非常大的负数(例如负无穷),这样在经过softmax操作后,这些位置的值将接近0,从而屏蔽了未来的信息。
4. 基于 Linear 和 Softmax 生成输出概率的详细过程
在 Transformer 的解码器中,生成输出概率的过程可以分为两个关键步骤:
- 线性层(Linear Layer):将解码器的输出映射到词汇表大小的维度。
- Softmax 函数:将线性层的输出转换为概率分布,选择概率最高的词作为预测结果。
下面作者将将通过一个详细的例子,逐步解释这个过程。
① 线性层(Linear Layer)
(1) 解码器的输出
- 解码器的输出是一个向量(或矩阵),表示当前时间步的隐藏状态。
- 假设解码器的输出是一个
d_model
** 维的向量**,例如[0.1, 0.3, 0.6]
,其中d_model
是模型的隐藏层维度。
(2) 线性层的作用
- 线性层的作用是将解码器的输出映射到与词汇表大小相匹配的维度。
- 假设词汇表大小为
V
(例如V = 10000
),线性层将输出一个V
维的向量。
(3) 线性层的实现
- 线性层是一个全连接层(Fully Connected Layer),其权重矩阵的形状为
[d_model, V]
。 - 假设
d_model = 3
,V = 3
,线性层的权重矩阵为:
python
W = [
[0.1, 0.2, 0.3],
[0.4, 0.5, 0.6],
[0.7, 0.8, 0.9]
]
- 线性层的计算公式为:
python
output = input @ W + b
其中 input
是解码器的输出,W
是权重矩阵,b
是偏置项(假设 b = [0, 0, 0]
)。
(4) 计算示例
- 输入向量:
[0.1, 0.3, 0.6]
- 线性层计算:
python
output = [0.1, 0.3, 0.6] @ [
[0.1, 0.2, 0.3],
[0.4, 0.5, 0.6],
[0.7, 0.8, 0.9]
] + [0, 0, 0]
计算过程:
python
output[0] = 0.1*0.1 + 0.3*0.4 + 0.6*0.7 = 0.01 + 0.12 + 0.42 = 0.55
output[1] = 0.1*0.2 + 0.3*0.5 + 0.6*0.8 = 0.02 + 0.15 + 0.48 = 0.65
output[2] = 0.1*0.3 + 0.3*0.6 + 0.6*0.9 = 0.03 + 0.18 + 0.54 = 0.75
- 线性层输出:
[0.55, 0.65, 0.75]
② Softmax 函数
(1) Softmax 的作用
- Softmax 函数将线性层的输出转换为概率分布,每个词汇对应一个概率值。
- 概率分布的范围是
[0, 1]
,且所有概率值的和为1
。
(2) Softmax 的计算公式
- 对于线性层的输出
[z1, z2, ..., zV]
,Softmax 的计算公式为:
python
softmax(zi) = exp(zi) / (exp(z1) + exp(z2) + ... + exp(zV))
(3) 计算示例
- 线性层输出:
[0.55, 0.65, 0.75]
- 计算 Softmax:
python
exp(0.55) = 1.733
exp(0.65) = 1.915
exp(0.75) = 2.117
sum_exp = 1.733 + 1.915 + 2.117 = 5.765
计算每个词的概率:
python
softmax(0.55) = 1.733 / 5.765 = 0.30
softmax(0.65) = 1.915 / 5.765 = 0.33
softmax(0.75) = 2.117 / 5.765 = 0.37
- Softmax 输出:
[0.30, 0.33, 0.37]
③ 选择预测结果
- Softmax 输出是一个概率分布,每个词对应一个概率值。
- 选择概率最高的词作为预测结果。
- 在上面的例子中,概率分布为
[0.30, 0.33, 0.37]
,概率最高的词是第三个词(概率为0.37
)。
简单整理一下:
步骤 | 输入 | 计算过程 | 输出 |
---|---|---|---|
线性层 | 解码器的输出向量(d_model 维) |
output = input @ W + b |
词汇表大小的向量(V 维) |
Softmax | 线性层的输出向量(V 维) |
softmax(zi) = exp(zi) / (exp(z1) + exp(z2) + ... + exp(zV)) |
概率分布(V 维) |
选择结果 | Softmax 输出的概率分布 | 选择概率最高的词 | 预测的下一个词 |
- 线性层将解码器的输出映射到词汇表大小的维度。
- Softmax将线性层的输出转换为概率分布。
- 选择结果根据概率分布选择预测的下一个词。
4. 预测过程
初始步骤:
- 输入准备:编码器处理输入序列(例如一篇文章的全文),解码器的初始输入包括编码器的编码结果和一个开始符号
<START>
。
生成序列:
- 预测第一个单词 :解码器基于编码器的输出和开始符号
<START>
来预测摘要的第一个单词,例如"Summary"。 - 迭代生成 :
- 第二步,输入"Summary",解码器可能会预测下一个单词"of"。
- 第三步,输入"Summary of",解码器接着预测"the"。
- 逐步构建:在每个步骤中,解码器的输出通过线性层调整维度,并通过Softmax函数转换为概率分布,选择概率最高的单词作为预测结果。
结束条件:
- 生成过程持续进行,直到解码器预测出序列结束的标记
<END>
。
完整示例:
- 输入
<START>
,输出"Summary"。 - 输入"Summary",输出"of"。
- 输入"Summary of",输出"the"。
- 输入"Summary of the",输出"key"。
- 输入"Summary of the key",输出"points"。
- 输入"Summary of the key points",输出
<END>
,表示摘要生成完毕。
5. 训练过程
问题:
- 如果模型没有收敛得很好,Decoder预测产生的词很可能不是我们想要的。这个时候如果再把错误的数据输给Decoder,就会越跑越偏。
解决方法:
- 在训练过程中,我们使用Teacher Forcing策略,即将正确的目标序列作为解码器的输入,而不是使用解码器自己预测的结果。这样可以加速模型的收敛。
损失函数:
- 在训练过程中,我们使用损失函数(例如交叉熵损失)将生成的输出概率分布与目标序列进行比较。概率分布给出了每个单词出现在该位置的概率。
例子:
- 假设目标词汇表包含四个单词,目标序列为"De nada END"。
- 第一个单词位置的概率分布中"De"的概率应该为1,其他单词的概率为0。
- 第二个单词位置"nada"的概率应该为1。
- 第三个单词位置"END"的概率应该为1。
- 损失函数计算预测概率分布与目标序列之间的差异,并通过反向传播来训练模型。
三、Decoder在不同阶段的信息传递机制
Decoder在Transformer模型中承担着生成输出序列的任务。它在预测阶段 和训练阶段有不同的信息传递机制,同时还需要通过评估指标来判断生成句子的质量。下面我们将详细探讨这些机制。
1. 预测阶段
在预测阶段,Decoder的目标是逐步生成输出序列。为了生成序列,Decoder需要选择下一个词,而选择策略直接影响生成结果的质量和效率。常见的策略包括:
① 穷举法(Exhaustive Search)
- 原理:穷举法会计算所有可能的输出序列,并选择条件概率最大的序列。
- 优点:可以保证全局最优解。
- 缺点:计算复杂度非常高,尤其是当词汇表很大或序列很长时,计算量会呈指数级增长。
- 例子 :
- 假设词汇表有3个词:
["A", "B", "C"]
,序列长度为2。 - 穷举法会计算所有可能的序列(如
["A", "A"]
、["A", "B"]
、["A", "C"]
等),并选择概率最大的序列。
- 假设词汇表有3个词:
② 贪心搜索(Greedy Search)
- 原理:在每个时间步,选择当前概率最高的词作为输出。
- 优点:计算简单,效率高。
- 缺点:只能保证局部最优,可能导致生成的序列不是全局最优。
- 例子 :
- 假设当前时间步的候选词概率为
["A": 0.4, "B": 0.5, "C": 0.1]
,贪心搜索会选择"B"
作为输出。
- 假设当前时间步的候选词概率为
③ 束搜索(Beam Search)
- 原理 :在贪心搜索的基础上,设置一个束宽(beam size),保留概率最高的
k
个候选序列。 - 优点:在效率和全局最优之间取得平衡。
- 缺点:束宽越大,计算量越大。
- 例子 :
- 假设束宽为2,当前时间步的候选词概率为
["A": 0.4, "B": 0.5, "C": 0.1]
,束搜索会保留"A"
和"B"
作为候选。 - 在下一个时间步,继续从这两个候选序列中扩展,选择概率最高的
k
个序列。
- 假设束宽为2,当前时间步的候选词概率为
2. 训练阶段
在训练阶段,Decoder的目标是学习如何生成正确的输出序列。为了加速训练并提高模型的稳定性,通常会使用**教师强制(Teacher Forcing)或计划采样(Scheduled Sampling)**策略。
① 自由运行模式(Free Running Mode)
- 原理:Decoder使用上一个时间步的预测值作为下一个时间步的输入。
- 缺点 :
- 如果模型在某一步预测错误,错误会累积,导致后续预测偏离正确轨迹。
- 训练效率低,模型收敛慢。
② 教师强制模式(Teacher Forcing Mode)
- 原理:Decoder使用真实的标签(ground truth)作为下一个时间步的输入。
- 优点 :
- 即使模型预测错误,它仍然可以接收到正确的信息,加速训练。
- 训练效率高,模型收敛快。
- 缺点 :
- 训练和预测阶段存在不一致性,因为预测时无法获得真实标签。
③ 计划采样(Scheduled Sampling)
- 原理 :动态结合教师强制和自由运行模式。以概率
p
使用模型预测值作为输入,以概率1-p
使用真实标签作为输入。 - 优点 :
- 既能获得真实标签的指导,又能逐渐学会依赖自己的预测。
- 提高模型在预测阶段的稳健性。
- 例子 :
- 假设
p = 0.7
,模型有70%的概率使用自己的预测值,30%的概率使用真实标签。
- 假设
3. 如何评估模型预测出的整个句子的质量
在训练和预测阶段,模型生成的句子需要与真实标签进行比较,以评估其质量。常用的评估指标包括:
① 困惑度(Perplexity)
- 定义:困惑度衡量模型对给定序列的预测能力。
- 公式:
plain
Perplexity = exp(-1/N * Σ log P(y_i | y_<i))
其中,N
是序列长度,P(y_i | y_<i)
是模型预测的概率。
- 解释 :
- 困惑度越低,表示模型预测能力越强。
- 理想情况下,困惑度接近词汇表大小。
② BLEU分数
- 定义:BLEU(Bilingual Evaluation Understudy)分数用于评估机器翻译文本的质量。
- 原理 :
- 比较生成句子与参考句子之间的n-gram匹配程度。
- 对过短的生成句子施加惩罚。
- 公式:
plain
BLEU = BP * exp(Σ w_n * log p_n)
其中,BP
是短句惩罚因子,w_n
是n-gram的权重,p_n
是n-gram的精确度。
- 解释 :
- BLEU分数范围是0到1,分数越高表示生成句子与参考句子越接近。
4. Teacher Forcing
① Teacher Forcing要解决什么问题?
- 问题 :
- 自由运行模式下,模型预测错误会累积,导致训练效率低下。
- 模型在训练早期预测能力弱,生成的错误结果会影响后续学习。
- 解决方案 :
- Teacher Forcing通过使用真实标签作为输入,避免错误累积,加速模型收敛。
② Teacher Forcing的工作原理
- 原理 :
- 在训练过程中,Decoder使用真实标签作为下一个时间步的输入,而不是模型预测值。
- 例子 :
- 假设真实标签序列为
["Tom", "put", "an", "apple"]
。 - 在训练时,Decoder会依次接收
["START", "Tom", "put", "an"]
作为输入,并预测["Tom", "put", "an", "apple"]
。
- 假设真实标签序列为
四、模型的训练与评估
这部分可以在机器学习篇章中找到相关内容,这里不做多概述!🙂👌
1. 训练过程
- 梯度下降和反向传播 :
- 通过损失函数(如交叉熵损失)计算预测值与真实值之间的差异。
- 使用梯度下降更新模型参数,最小化损失。
- 学习率调度 :
- 动态调整学习率,例如使用热身计划或衰减计划。
2. 评估指标
- 困惑度:衡量模型预测能力。
- BLEU分数:评估生成句子的质量。
总结一下就是:
阶段 | 机制 | 优点 | 缺点 |
---|---|---|---|
预测阶段 | 穷举法、贪心搜索、束搜索 | 穷举法保证全局最优,束搜索平衡效率与质量 | 穷举法计算复杂度高,贪心搜索可能陷入局部最优 |
训练阶段 | 教师强制、计划采样 | 教师强制加速训练,计划采样提高模型稳健性 | 教师强制导致训练与预测不一致 |
评估指标 | 困惑度、BLEU分数 | 困惑度衡量预测能力,BLEU分数评估生成质量 | BLEU分数对短句惩罚可能过于严格 |
总结
Decoder作为Transformer模型的核心组件之一,承担着生成输出序列的重要任务。**通过掩码机制(Masking)和填充机制(Padding),Decoder能够有效处理变长序列并确保生成过程的因果性。多头自注意力机制(Masked Multi-Head Attention)和编码器-解码器注意力交互(Encoder-Decoder Attention)的结合,使得Decoder能够捕捉输入序列的全局信息并生成受上下文影响的输出。**在训练阶段,教师强制(Teacher Forcing)和计划采样(Scheduled Sampling)策略的引入,显著提升了模型的训练效率和生成质量。😉
🎉OK!今天就学习到这里了!🙂
项目地址
如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.