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(训练函数/损失函数)

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这些警告信息表明在模型的训练过程中,一些模块被视为无操作(zero-op)。这通常是由于模型的某些部分没有被正确地使用或设置导致的。以下是对每个警告的简要解释: - Dropout模块:Dropout是一种常用的正则化技术,但在推理阶段通常不需要使用。如果在推理阶段使用了Dropout模块,它会被视为无操作。 - PositionalEncoding模块:Transformer模型使用Positional Encoding来编码输入序列的位置信息。但在某些情况下,如果没有正确地设置Positional Encoding模块,它可能被视为无操作。 - NonDynamicallyQuantizableLinear模块:这个警告通常出现在使用量化技术对模型进行压缩时。NonDynamicallyQuantizableLinear是指无法动态量化的线性层,可能会被视为无操作。 - TransformerEncoderLayer模块:TransformerEncoderLayerTransformer模型中的一个关键组件,但在某些情况下,如果没有正确地使用或配置该模块,它可能被视为无操作。 - TransformerEncoder模块:TransformerEncoder是由多个TransformerEncoderLayer组成的编码器似于上述警告,如果没有正确地配置该模块,它可能被视为无操作。 - PredictionTransformer模块:这个警告出现在CSDN开发的具体模型中,可能是该模型使用了一些自定义的组件或层,但没有正确地使用或配置导致被视为无操作。 要解决这些警告,你需要检查相应的模块的使用和配置,确保其正常运行,并根据需要进行调整和修复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器学习杨卓越

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值