文章目录
相关文章
Transformer架构:结构介绍:网页链接
Transformer架构:输入部分代码实现(基于PyTorch):网页链接
Transformer架构:核心模块代码实现(基于PyTorch):网页链接
一、编码器的核心作用
在Transformer架构中,编码器(Encoder)是特征提取的核心模块,负责将输入序列(如文本、图像patch)转换为包含上下文信息的特征表示。其核心能力体现在:
- 上下文建模:通过自注意力机制捕捉序列中任意位置的依赖关系(如文本中“代词”与“指代对象”的关联)。
- 特征逐层抽象:通过多层堆叠的编码器层,从输入中逐层提取从简单到复杂的特征(如文本中从“词向量”→“短语语义”→“句子主题”)。
二、编码器整体工作流程图
核心模块的代码实现在 Transformer架构:核心模块代码实现(基于PyTorch) 中
三、编码器层(EncoderLayer):单一层级的特征变换
编码器层是构成编码器的基本单元,每个层包含“自注意力子层”和“前馈网络子层”,通过子层连接结构实现特征的深度加工。
3.1 代码实现与结构解析
class EncoderLayer(nn.Module):
def __init__(self, embedding_dim, self_attention, feedforward, dropout):
super().__init__()
self.self_attention = self_attention # 多头自注意力模块
self.feedforward = feedforward # 前馈全连接模块
self.embedding_dim = embedding_dim # 词嵌入维度(如512)
# 克隆2个子层连接结构(分别用于注意力子层和前馈子层)
self.sublayer = clones(SublayerConnection(embedding_dim, dropout), 2)
def forward(self, x, mask):
# 第一个子层:自注意力 + 残差连接 + 规范化
x = self.sublayer[0](x, lambda x: self.self_attention(x, x, x, mask))
# 第二个子层:前馈网络 + 残差连接 + 规范化
x = self.sublayer[1](x, self.feedforward)
return x
3.2 关键细节解析:
-
模块依赖:
self_attention
:多头注意力实例(如8头,MultiHeadedAttention
类),用于计算自注意力。feedforward
:前馈网络实例(PositionwiseFeedForward
类),用于非线性特征变换。sublayer
:通过clones
函数复制的2个子层连接结构,封装了“残差连接+LayerNorm+Dropout”逻辑。
-
前向传播流程:
- 自注意力子层:
输入x
通过lambda x: self.self_attention(x, x, x, mask)
实现自注意力计算(query=key=value=x
),再经self.sublayer[0]
完成残差连接与规范化。 - 前馈网络子层:
注意力输出通过前馈网络进行非线性变换,再经self.sublayer[1]
处理,最终输出当前编码器层的结果。
- 自注意力子层:
-
张量形状变化:
输入x
形状为[batch_size, seq_len, embedding_dim]
,经过两层子处理后形状保持不变,确保多层堆叠时的兼容性。
四、编码器(Encoder):多层堆叠的深度特征提取
编码器由N
个相同的编码器层堆叠而成,通过多层迭代强化特征表示,最终输出包含全局上下文的序列特征。
4.1 代码实现与结构解析
class Encoder(nn.Module):
def __init__(self, layer, N):
super().__init__()
# 克隆N个编码器层(如N=6,构成6层编码器)
self.layers = clones(layer, N)
# 最终规范化层(输出前的最后一次特征分布调整)
self.norm = LayerNorm(embedding_dim)
def forward(self, x, mask):
# 依次通过N个编码器层
for layer in self.layers:
x = layer(x, mask)
# 最终规范化
return self.norm(x)
4.2 关键细节解析:
-
多层堆叠逻辑:
通过clones(layer, N)
复制N
个相同的编码器层(如Transformer原论文中N=6
),形成深度网络结构。每层的输出作为下一层的输入,实现特征的逐层抽象。 -
最终规范化:
所有编码器层处理完毕后,通过LayerNorm
进行最终规范化,确保输出特征的分布稳定性,为后续解码器(或下游任务)提供一致的输入。 -
掩码作用:
mask
在整个编码器流程中传递,用于屏蔽输入序列中的无效位置(如填充的PAD
token),确保自注意力计算仅关注有效元素。
五、核心设计思想
-
模块化堆叠:
编码器层通过“自注意力+前馈网络”的固定模块重复堆叠,平衡了模型复杂度与可扩展性。增加层数可提升特征抽象能力,但需配合残差连接避免梯度消失。 -
自注意力的核心价值:
每个编码器层中的自注意力机制允许序列中的每个元素“关注”其他所有元素,从而捕捉长距离依赖(如文本中跨句子的语义关联),这是Transformer超越RNN的关键。 -
与输入模块的衔接:
编码器的输入通常是经过“词嵌入+位置编码”的序列(见《Transformer架构:输入部分代码实现》),其输出可直接作为解码器的“记忆”(如机器翻译任务),或用于文本分类等下游任务。
六、完整代码
from Transformer_moduls import *
# 编码器层类 EncoderLayer 实现思路分析
# init函数 (self, size, self_attn, feed_forward, dropout):
# 实例化多头注意力层对象self_attn # 前馈全连接层对象feed_forward size词嵌入维度512
# clones两个子层连接结构 self.sublayer = clones(SublayerConnection(size,dropout),2)
# forward函数 (self, x, mask)
# 数据经过子层连接结构1 self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))
# 数据经过子层连接结构2 self.sublayer[1](x, self.feed_forward)
class EncoderLayer(nn.Module):
def __init__(self,embedding_dim,self_attention,feedforward,dropout):
super().__init__()
# 实例化多头注意力层对象
self.self_attention = self_attention
# 前馈全连接层对象feed_forward
self.feedforward = feedforward
# size词嵌入维度512
self.embedding_dim = embedding_dim
# clones两个子层连接结构 self.sublayer = clones(SublayerConnection(size,dropout),2)
self.sublayer = clones(SublayerConnection(embedding_dim,dropout),2)
def forward(self,x,mask):
x = self.sublayer[0](x, lambda x:self.self_attention(x,x,x,mask))
x = self.sublayer[1](x,self.feedforward)
return x
# 编码器类 Encoder 实现思路分析
# init函数 (self, layer, N)
# 实例化多个编码器层对象self.layers 通过方法clones(layer, N)
# 实例化规范化层 self.norm = LayerNorm(layer.size)
# forward函数 (self, x, mask)
# 数据经过N个层 x = layer(x, mask)
# 返回规范化后的数据 return self.norm(x)
class Encoder(nn.Module):
def __init__(self,layer,N):
# 参数layer 1个编码器层
# 参数 编码器层的个数
super().__init__()
# 实例化多个编码器层对象
self.layers = clones(layer,N)
# 实例化规范化层
self.norm = LayerNorm(embedding_dim)
def forward(self,x,mask):
# 数据经过N个层 x = layer(x, mask)
for layer in self.layers:
x = layer(x,mask)
# 返回规范化后的数据 return self.norm(x)
return self.norm(x)
def test_encoder():
x = torch.arange(8).reshape(2,-1)
x = untest_input(x)
self_attention = MutiHeadAttention(8,embedding_dim,dropout)
feedforward = PositionwiseFeedForward(embedding_dim,d_ff)
encoder_layer = EncoderLayer(embedding_dim,self_attention,feedforward,dropout)
encoder = Encoder(encoder_layer,6)
# 此处应该使用padding mask,为演示方便用全0mask
mask = torch.zeros(heads,4,4)
encoder_result = encoder(x,mask)
print(f'{"*"*30}编码后的值{"*"*30}')
print(encoder_result)
print(f'编码后的形状:{encoder_result.shape}')
return encoder_result
if __name__ == '__main__':
test_encoder()