Transformer模型实现与测试梳理
Transformer模型实现与测试梳理
一、解码器层(DecoderLayer)
1. 核心代码
class DecoderLayer(nn.Module):def __init__(self, size, adn, source, feed_forward, dropout):super(DecoderLayer, self).__init__()self.size = size # 自注意力维度self.adn = adn # 多头自注意力机制对象(q=k=v)self.source = source # 多头注意力机制对象(k=v)self.feed_forward = feed_forward # 前馈全连接层对象self.sublayers = clones(SublayerConnection(size, dropout), 3) # 3个子层连接def forward(self, x, memory, source_mask, target_mask):m = memory# 第一个子层:自注意力(带target mask)x = self.sublayers[0](x, lambda x: self.adn(x, x, x, target_mask))# 第二个子层:编码器-解码器注意力(带source mask)x = self.sublayers[1](x, lambda x: self.source(x, m, m, source_mask))# 第三个子层:前馈网络return self.sublayers[2](x, self.feed_forward)
2. 注意事项
target_mask
用于防止未来信息泄露(遮挡后续时间步),source_mask
用于忽略padding部分影响。- 输入
x
需先经过词嵌入(embedding)和位置编码(position encoding)处理,否则会报错。 - 三个子层需严格按顺序执行:自注意力→编码器-解码器注意力→前馈网络。
3. 执行流程
- 输入
x
(解码器输入)经过第一个子层,通过自注意力机制处理,结合target_mask
生成中间结果。 - 中间结果进入第二个子层,与编码器输出
memory
进行交叉注意力计算,结合source_mask
。 - 结果经过第三子层的前馈网络,输出最终解码器层结果。
二、解码器(Decoder)
1. 核心代码
class Decoder(nn.Module):def __init__(self, layer, n):super(Decoder, self).__init__()self.layers = clones(layer, n) # 克隆n个解码器层self.norm = LayerNorm(layer.size) # 最终规范化层def forward(self, x, memory, source_mask, target_mask):for layer in self.layers:x = layer(x, memory, source_mask, target_mask) # 逐层处理return self.norm(x) # 最终规范化
2. 注意事项
n
为解码器层数(通常设为6),需与编码器层数保持一致。- 每一层解码器都会复用编码器输出
memory
和掩码,仅输入x
随层更新。 - 最终输出需经过规范化处理,保证数据分布稳定。
3. 执行流程
- 输入
x
(经嵌入和位置编码的解码器输入)依次通过n
个解码器层。 - 每层均接收
memory
(编码器输出)、source_mask
和target_mask
。 - 所有层处理完成后,通过规范化层输出最终结果。
三、输出层(Generator)
1. 核心代码
class Generator(nn.Module):def __init__(self, d_model, vocab_size):super(Generator, self).__init__()self.linear = nn.Linear(d_model, vocab_size) # 线性层(维度转换)def forward(self, x):# 线性层转换维度后,应用log_softmaxreturn F.log_softmax(self.linear(x), dim=-1)
2. 注意事项
d_model
需与解码器输出维度一致(通常为512),vocab_size
为目标语言词表大小。- 使用
log_softmax
而非softmax
,便于后续计算交叉熵损失。 - 输出形状为
(batch_size, seq_len, vocab_size)
,每个位置对应词表中所有单词的概率。
3. 执行流程
- 输入
x
(解码器输出,形状为(batch_size, seq_len, d_model)
)。 - 经线性层转换为
(batch_size, seq_len, vocab_size)
。 - 应用
log_softmax
得到每个位置的单词概率分布,输出最终预测结果。
四、模型组装(Encoder-Decoder)
1. 核心代码
class EncoderDecoder(nn.Module):def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):super(EncoderDecoder, self).__init__()self.encoder = encoder # 编码器self.decoder = decoder # 解码器self.src_embed = src_embed # 源语言嵌入(含位置编码)self.tgt_embed = tgt_embed # 目标语言嵌入(含位置编码)self.generator = generator # 输出层def forward(self, src, tgt, src_mask, tgt_mask):# 编码源语言输入memory = self.encode(src, src_mask)# 解码并生成输出return self.decode(memory, src_mask, tgt, tgt_mask)def encode(self, src, src_mask):return self.encoder(self.src_embed(src), src_mask)def decode(self, memory, src_mask, tgt, tgt_mask):return self.decoder(self.tgt_embed(tgt), memory, src_mask, tgt_mask)
2. 注意事项
src_embed
和tgt_embed
需分别封装源语言和目标语言的词嵌入与位置编码(可用nn.Sequential
合并)。src_mask
和tgt_mask
需区分:前者为源语言padding掩码,后者包含padding掩码和未来信息掩码。- 模型整体输入为原始文本序列(需转换为索引),输出为目标语言词表概率分布。
3. 执行流程
- 源语言输入
src
经src_embed
处理后,送入编码器生成memory
。 - 目标语言输入
tgt
经tgt_embed
处理后,与memory
一同送入解码器。 - 解码器输出经输出层
generator
处理,得到最终预测结果。
五、关键工具与函数
1. nn.Sequential
与nn.ModuleList
对比
工具 | 特点 | 应用场景 |
---|---|---|
nn.Sequential | 按顺序执行网络层,输入输出需匹配维度 | 层与层顺序固定时(如嵌入+位置编码) |
nn.ModuleList | 仅存储层对象,无顺序执行逻辑 | 需要灵活调用层时(如动态选择子层) |
2. clones
函数(层克隆)
def clones(module, N):"克隆N个相同的模块"return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])
- 用于生成多个相同配置的编码器层或解码器层,避免共享参数。
六、总结
-
模块分工:
- 解码器层:实现自注意力、交叉注意力和前馈网络,处理单层级计算。
- 解码器:堆叠多层解码器层,逐步优化输出结果。
- 输出层:将解码器输出转换为目标词表概率分布。
- 模型组装:串联编码器、解码器、嵌入层和输出层,形成完整Transformer。
-
核心要点:
- 掩码机制是关键:
target_mask
防止未来信息泄露,source_mask
处理padding。 - 维度一致性:各模块输入输出维度需匹配(如
d_model
贯穿始终)。 - 模块化设计:通过克隆层和封装函数简化代码,提高复用性。
- 掩码机制是关键:
-
执行逻辑:原始文本→嵌入+位置编码→编码器→解码器→输出层→预测结果,全流程严格按顺序执行,确保注意力机制有效捕捉序列依赖。