Transformer 代码剖析8 - 编码器模块Encoder (pytorch实现)

一、代码结构总览

Transformer Encoder
__init__初始化
Encoder类
forward前向传播
super()父类初始化
构建词嵌入层
self.emb=TransformerEmbedding
参数:d_model/max_len/vocab_size/drop_prob/device
构建编码层堆栈
self.layers=nn.ModuleList
循环创建n_layers个EncoderLayer
参数:d_model/ffn_hidden/n_head/drop_prob
嵌入转换:x=self.emb(x)
编码层迭代处理
遍历self.layers 列表
调用layer(x, src_mask)
返回编码结果x
torch.nn
EncoderLayer
TransformerEmbedding

二、构造函数深度解析

2.1 类定义与初始化流程

__init__ 入口
调用父类构造器
初始化词嵌入层
参数绑定:d_model/max_len等
构建编码层堆栈
循环创建n_layers个EncoderLayer
封装为ModuleList

核心代码段:

def __init__(self, enc_voc_size, max_len, d_model, ffn_hidden, n_head, n_layers, drop_prob, device):
    super().__init__()
    self.emb = TransformerEmbedding(
        d_model=d_model,
        max_len=max_len,
        vocab_size=enc_voc_size,
        drop_prob=drop_prob,
        device=device)
    
    self.layers = nn.ModuleList([EncoderLayer(
        d_model=d_model,
        ffn_hidden=ffn_hidden,
        n_head=n_head,
        drop_prob=drop_prob) 
        for _ in range(n_layers)])

2.2 参数语义解析表

参数名 类型 作用域 典型值示例 数学意义
enc_voc_size int 词嵌入层 5000 源语言词汇表维度
max_len int 位置编码 512 最大序列长度
d_model int 全模块 768 隐藏层维度空间
ffn_hidden int 前馈网络 3072 膨胀系数(通常4倍d_model)
n_head int 注意力机制 12 并行注意力头数
n_layers int 编码器堆叠 6 深度网络层次
drop_prob float 正则化 0.1 神经元失活概率
device str 计算设备 “cuda:0” 张量运算载体

2.3 张量维度演化示例

假设输入序列:

  • batch_size = 32
  • seq_len = 10
  • 词汇表大小 = 5000
x = torch.randint(0, 5000, (32, 10))  # shape: [32,10]
src_mask = None 
 
# 经过词嵌入层后 
emb_out = self.emb(x)  # shape: [32,10,768]
 
# 首层编码器处理 
layer1_out = self.layers  # shape保持[32,10,768]

三、前向传播机制解析

3.1 执行流程图解

输入张量x
Token Embedding
Positional Encoding
Add&Norm
循环n次
多头注意力
残差连接
前馈网络
层归一化
输出编码

3.2 关键代码段分析

def forward(self, x, src_mask):
    x = self.emb(x)  # 嵌入层融合 
    
    # 层次处理循环 
    for layer in self.layers: 
        x = layer(x, src_mask)  # 特征空间变换 
        
    return x  # 上下文感知表示 

运算过程数学表达:
设第 l l l层处理函数为 E l E_l El,则整体编码过程可表示为:
h 0 = Embedding ( x ) + PositionalEncoding ( x ) h l = E l ( h l − 1 , M s r c ) , l = 1 , 2 , . . . , L Output = h L \begin{aligned} h_0 &= \text{Embedding}(x) + \text{PositionalEncoding}(x) \\ h_l &= E_l(h_{l-1}, M_{src}), \quad l=1,2,...,L \\ \text{Output} &= h_L \end{aligned} h0hlOutput=Embedding(x)+PositionalEncoding(x)=El(hl1,Msrc),l=1,2,...,L=hL

其中 M s r c M_{src} Msrc为源序列掩码矩阵。

四、模块设计原理剖析

4.1 词嵌入子系统

Input Tokens
Token Embedding Lookup
Positional Encoding
Dropout
Layer Normalization
  • Token Embedding:可训练的查找表,将离散符号映射到连续空间
  • 位置编码:使用固定公式生成位置特征:
    P E ( p o s , 2 i ) = sin ⁡ ( p o s / 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i + 1 ) = cos ⁡ ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos,2i)} = \sin(pos/10000^{2i/d_{model}}) \\ PE_{(pos,2i+1)} = \cos(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)

跳转到章节: 词元嵌入

4.2 编码层堆叠设计

每个EncoderLayer包含:
1. 多头自注意力机制
2. 残差连接+层归一化
3. 位置前馈网络
4. 二次残差连接+归一化

跳转到章节: 编码层解析

五、工程实践要点

5.1 设备兼容性设计

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
encoder = Encoder(...).to(device)

5.2 内存优化策略

  • ModuleList: 确保所有子模块参数可被正确注册
  • 参数共享: 所有编码层共享相同结构但独立参数
  • 梯度计算: 通过残差连接保持梯度流动

5.3 典型应用场景

场景 配置参数示例 硬件要求
机器翻译 d_model=512, n_layers=6 16GB GPU
文本摘要 ffn_hidden=2048, n_head=8 24GB GPU
语音识别 max_len=3000 特殊硬件加速

六、性能优化建议

1. 混合精度训练: 使用torch.cuda.amp自动类型转换
2. 激活检查点: 通过torch.utils.checkpoint节省显存
3. 内核融合: 使用PyTorch JIT编译优化计算图
4. 流水线并行: 当n_layers>12时建议分层部署


原项目代码(附)

"""
@author : Hyunwoong
@when : 2019-12-18
@homepage : https://github.com/gusdnd852
"""

from torch import nn

# 从其他模块导入EncoderLayer和TransformerEmbedding类
from models.blocks.encoder_layer import EncoderLayer
from models.embedding.transformer_embedding import TransformerEmbedding

# 定义一个名为Encoder的类,它继承自nn.Module,用于实现Transformer模型的编码器部分
class Encoder(nn.Module):

    def __init__(self, enc_voc_size, max_len, d_model, ffn_hidden, n_head, n_layers, drop_prob, device):
        # 调用父类nn.Module的构造函数
        super().__init__()
        # 初始化词嵌入层,用于将输入序列转换为向量表示
        self.emb = TransformerEmbedding(d_model=d_model,  # 向量维度
                                        max_len=max_len,  # 序列最大长度
                                        vocab_size=enc_voc_size,  # 词汇表大小
                                        drop_prob=drop_prob,  # Dropout概率
                                        device=device)  # 设备配置(CPU或GPU)

        # 初始化编码器层列表,包含多个EncoderLayer实例
        self.layers = nn.ModuleList([EncoderLayer(d_model=d_model,  # 向量维度
                                                  ffn_hidden=ffn_hidden,  # 前馈神经网络隐藏层维度
                                                  n_head=n_head,  # 多头注意力头数
                                                  drop_prob=drop_prob)  # Dropout概率
                                     for _ in range(n_layers)])  # 编码器层数

    def forward(self, x, src_mask):
        # 将输入序列x通过词嵌入层转换为向量表示
        x = self.emb(x)

        # 遍历编码器层列表,将向量表示x和源序列掩码src_mask依次通过每个编码器层
        for layer in self.layers:
            x = layer(x, src_mask)

        # 返回经过编码器处理后的向量表示x
        return x

参考: 项目代码

你可能感兴趣的:(Transformer代码剖析,transformer,pytorch,深度学习,人工智能,python)