Transformer实战-系列教程19:DETR 源码解读6(编码器:TransformerEncoder类/TransformerEncoderLayer类)

Transformer实战-系列教程总目录

有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传
点我下载源码

DETR 算法解读
DETR 源码解读1(项目配置/CocoDetection类/ConvertCocoPolysToMask类)
DETR 源码解读2(DETR类)
DETR 源码解读3(位置编码:Joiner类/PositionEmbeddingSine类)
DETR 源码解读4(BackboneBase类/Backbone类)
DETR 源码解读5(Transformer类)
DETR 源码解读6(编码器:TransformerEncoder类/TransformerEncoderLayer类)
DETR 源码解读7(解码器:TransformerDecoder类/TransformerDecoderLayer类)
DETR 源码解读8(训练函数/损失函数)

10、TransformerEncoderLayer类

位置:models/transformer.py/TransformerEncoderLayer类

TransformerEncoderLayer实现了一个标准的Transformer编码器层,支持位置编码的加入、自注意力机制、前馈网络、残差连接以及层归一化等关键操作

这些组件和操作共同定义了Transformer架构中编码器层的核心功能

TransformerEncoder编码器是使用编码器层TransformerEncoderLayer堆叠起来的

10.1 构造函数

class TransformerEncoderLayer(nn.Module):
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1, activation="relu", normalize_before=False):
        super().__init__()
        self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)
        self.linear1 = nn.Linear(d_model, dim_feedforward)
        self.dropout = nn.Dropout(dropout)
        self.linear2 = nn.Linear(dim_feedforward, d_model)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)
        self.activation = _get_activation_fn(activation)
        self.normalize_before = normalize_before
  1. 继承PyTorch的nn.Module
  2. 构造函数,传入以下6个参数:
    • d_model:模型维度
    • nhead:多头注意力的头数
    • dim_feedforward:MLP全连接的输出维度
    • dropout:涉及到全连接层dropout比率
    • activation:激活函数
    • normalize_before:归一化是在Attention和MLP之间进行还是在MLP之后进行
  3. 初始化
  4. self_attn ,创建一个torch.nn的多头自注意力模块
  5. linear1 ,MLP的第1个全连接层
  6. dropout ,定义一层dropout
  7. linear2 ,MLP的第2个全连接层
  8. norm1 ,Attention层输出的层归一化
  9. norm2 ,MLP输出的层归一化
  10. dropout1 , Attention层输出的dropout
  11. dropout2 ,MLP输出的dropout
  12. activation ,使用一个辅助函数定义激活函数
  13. normalize_before ,归一化是在Attention和MLP之间进行(True)还是在MLP之后进行(False)

10.2 前向传播

    def forward(self, src, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None):
        if self.normalize_before:
            return self.forward_pre(src, src_mask, src_key_padding_mask, pos)
        return self.forward_post(src, src_mask, src_key_padding_mask, pos)
  1. 前向传播函数
  2. self.normalize_before为true
  3. 使用forward_pre函数进行前向传播
  4. 否则使用forward_post进行前向传播

10.3 forward_post函数

    def forward_post(self, src, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None):
        q = k = self.with_pos_embed(src, pos)
        src2 = self.self_attn(q, k, value=src, attn_mask=src_mask, key_padding_mask=src_key_padding_mask)[0]
        src = src + self.dropout1(src2)
        src = self.norm1(src)
        src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))
        src = src + self.dropout2(src2)
        src = self.norm2(src)
        return src
  1. 可选的前向传播函数,传入源数据src、可选的掩码src_mask、可选的填充掩码src_key_padding_mask和可选的位置编码pos
  2. q,k,torch.Size([725, 2, 256]),把数据源和位置编码相加生成q和k,725是序列长度、2是batch、256是每个向量维度
  3. src2 ,torch.Size([725, 2, 256]),调用多头自注意力模块,传入q、k、v向量,以及可选的注意力掩码和填充掩码,v就是backbone生成的特征图再转换的序列
  4. src ,torch.Size([725, 2, 256]),将注意力模块的输出经过dropout后与原始输入相加,实现残差连接
  5. src ,torch.Size([725, 2, 256]),经过一个层归一化
  6. src2 ,torch.Size([725, 2, 256]),相当于实现一个MLP,上一层的输出src 按照顺序先后经过:第1个全连接层、激活函数、Dropout、第2个全连接层,在第2个全连接层维度变回725
  7. src ,torch.Size([725, 2, 256]),将MLP的输出经过dropout后与原始输入相加,实现残差连接
  8. torch.Size([725, 2, 256]),经过一个层归一化
  9. return

10.4 forward_pre函数

    def forward_pre(self, src, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None):
        src2 = self.norm1(src)
        q = k = self.with_pos_embed(src2, pos)
        src2 = self.self_attn(q, k, value=src2, attn_mask=src_mask, key_padding_mask=src_key_padding_mask)[0]
        src = src + self.dropout1(src2)
        src2 = self.norm2(src)
        src2 = self.linear2(self.dropout(self.activation(self.linear1(src2))))
        src = src + self.dropout2(src2)
        return src
    def with_pos_embed(self, tensor, pos: Optional[Tensor]):
        return tensor if pos is None else tensor + pos

forward_pre方法,用于在normalize_before设置为True时执行前向传播。这种情况下,层归一化会在自注意力和前馈网络操作之前应用。该方法接受与forward_post相同的参数:输入数据src、可选的掩码src_mask和src_key_padding_mask,以及可选的位置编码pos

主要操作和forward_post一致,只有执行层归一化的位置不同

with_pos_embed函数,将位置编码和数据源相加,其中位置编码是可选的

11、TransformerEncoder类

位置:models/transformer.py/TransformerEncoder类
TransformerEncoder将TransformerEncoderLayer进行堆叠,构成编码器

class TransformerEncoder(nn.Module):
    def __init__(self, encoder_layer, num_layers, norm=None):
        super().__init__()
        self.layers = _get_clones(encoder_layer, num_layers)
        self.num_layers = num_layers
        self.norm = norm
    def forward(self, src, mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None): 
    	output = src
        for layer in self.layers:
            output = layer(output, src_mask=mask, src_key_padding_mask=src_key_padding_mask, pos=pos)
        if self.norm is not None:
            output = self.norm(output)
        return output
  1. 继承nn.Module的类
  2. 构造函数,传入3个参数:encoder_layer单个编码器层、num_layers编码器层堆叠的数量、norm可选的归一化模块
  3. 初始化
  4. 使用_get_clones辅助函数,传入2两个参数,堆叠所有的编码器层
  5. num_layers
  6. norm
  7. 前向传播函数,传入4个参数:src图像序列、mask可选的掩码、src_key_padding_mask可选的填充掩码、pos可选的位置编码
  8. output ,torch.Size([725, 2, 256])
  9. 循环遍历所有堆叠的编码器层
  10. output ,torch.Size([725, 2, 256]),传入当前的输出output、掩码和位置编码,每层的输出会更新output,供下一层使用
  11. 是否需要进行归一化
  12. output,torch.Size([725, 2, 256]),经过一个层归一化
  13. return

DETR 算法解读
DETR 源码解读1(项目配置/CocoDetection类/ConvertCocoPolysToMask类)
DETR 源码解读2(DETR类)
DETR 源码解读3(位置编码:Joiner类/PositionEmbeddingSine类)
DETR 源码解读4(BackboneBase类/Backbone类)
DETR 源码解读5(Transformer类)
DETR 源码解读6(编码器:TransformerEncoder类/TransformerEncoderLayer类)
DETR 源码解读7(解码器:TransformerDecoder类/TransformerDecoderLayer类)
DETR 源码解读8(训练函数/损失函数)

你可能感兴趣的:(Transformer实战,transformer,深度学习,pytorch,DETR,人工智能,计算机视觉)