12,049
社区成员
发帖
与我相关
我的任务
分享python
class DecoderLayer(nn.Module):
def __init__(self, size, adn, source, feed_forward, dropout):
super().__init__()
self.size = size # 自注意力维度
self.adn = adn # 多头自注意力(q=k=v)
self.source = source # 编码器-解码器注意力(k=v用memory)
self.feed_forward = feed_forward # 前馈网络
self.sublayers = clones(SublayerConnection(size, dropout), 3) # 残差+归一化封装
def forward(self, x, memory, source_mask, target_mask):
# 1. 自注意力(防未来信息泄露,用target_mask)
x = self.sublayers[0](x, lambda x: self.adn(x, x, x, target_mask))
# 2. 编码器-解码器注意力(对齐源文本,用source_mask)
x = self.sublayers[1](x, lambda x: self.source(x, memory, memory, source_mask))
# 3. 前馈网络(维度变换+非线性)
return self.sublayers[2](x, self.feed_forward)
target_mask 遮掉后续词(翻译时不能偷看未来内容),source_mask 忽略源文本里的 padding。python
class Decoder(nn.Module):
def __init__(self, layer, n):
super().__init__()
self.layers = clones(layer, n) # 克隆n层(通常n=6)
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) # 统一输出分布,方便后续计算
memory(编码器输出),但 x 会随着层堆叠不断优化,像 “草稿→精修” 的过程。python
class Generator(nn.Module):
def __init__(self, d_model, vocab_size):
super().__init__()
self.linear = nn.Linear(d_model, vocab_size) # 把解码器输出维度转成词表大小
def forward(self, x):
# log_softmax方便算交叉熵损失,输出每个位置的词概率
return F.log_softmax(self.linear(x), dim=-1)
[batch, seq_len, d_model]),输出是 [batch, seq_len, vocab_size],每个位置对应词表所有词的概率。log_softmax 而不是普通 softmax,数值计算更稳定,训练时算损失更方便。python
class EncoderDecoder(nn.Module):
def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):
super().__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):
# 1. 编码源文本
memory = self.encode(src, src_mask)
# 2. 解码并生成结果
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)
src 先过 src_embed(词嵌入 + 位置编码),再丢给编码器生成 memory(理解后的源文本特征)。tgt 过 tgt_embed 后,带着 memory 进解码器,逐层优化后,用 generator 转成词概率。clones 函数(层克隆)python
def clones(module, N):
return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])
nn.Sequential vs nn.ModuleList| 工具 | 特点 | 用在哪? |
|---|---|---|
nn.Sequential | 层会按顺序执行,输入输出必须 “对上维度” | 固定流程(如 词嵌入→位置编码) |
nn.ModuleList | 只存层,不自动执行 | 需灵活调用(如解码器的多层迭代) |
target_mask 遮未来,source_mask 跳 padding)、维度要对齐(d_model 贯穿全程)、多层迭代优化(解码器堆 6 层打磨结果)。
想自己实现 Transformer?照着这个结构,把编码器、注意力机制补上,就能跑通完整流程啦~ 有疑问评论区见!