🚩🚩🚩Transformer实战-系列教程总目录
有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Pycharm中进行
本篇文章配套的代码资源已经上传
点我下载源码
DETR 算法解读
DETR 源码解读1(项目配置/CocoDetection类)
DETR 源码解读2(ConvertCocoPolysToMask类)
DETR 源码解读3(DETR类)
DETR 源码解读4(Joiner类/PositionEmbeddingSine类/位置编码/backbone)
9、Transformer类
位置:models/transformer.py/Transformer类
9.1 _reset_parameters()函数
def _reset_parameters(self):for p in self.parameters():if p.dim() > 1:nn.init.xavier_uniform_(p)
这个辅助函数,遍历当前被调用的模型中所有的参数,当这个参数的维度大于1时,会对当前参数使用Xavier均匀初始化方法进行初始化
9.2 构造函数
class Transformer(nn.Module):def __init__(self, d_model=512, nhead=8, num_encoder_layers=6,num_decoder_layers=6, dim_feedforward=2048, dropout=0.1,activation="relu", normalize_before=False,return_intermediate_dec=False):super().__init__()encoder_layer = TransformerEncoderLayer(d_model, nhead, dim_feedforward, dropout, activation, normalize_before)encoder_norm = nn.LayerNorm(d_model) if normalize_before else Noneself.encoder = TransformerEncoder(encoder_layer, num_encoder_layers, encoder_norm)decoder_layer = TransformerDecoderLayer(d_model, nhead, dim_feedforward, dropout, activation, normalize_before)decoder_norm = nn.LayerNorm(d_model)self.decoder = TransformerDecoder(decoder_layer, num_decoder_layers, decoder_norm, return_intermediate=return_intermediate_dec)self._reset_parameters()self.d_model = d_modelself.nhead = nhead
- 定义类,继承PyTorch的nn.Module
- 构造函数,传入模型维度、多头注意力的头数、编码器层数、解码器层数、前馈网络的维度、dropout比率、激活函数类型、是否在层之前进行归一化处理、是否返回解码器的中间层输出
- 初始化
- encoder_layer ,使用TransformerEncoderLayer类创建一个编码器层
- encoder_norm ,根据normalize_before的值决定是否创建一个层归一化层
- encoder ,使用TransformerEncoder类调用编码器层、编码器层数、归一化等创建编码器
- decoder_layer ,使用TransformerDecoderLayer类创建一个解码器层
- decoder_norm ,创建一个层归一化层
- decoder ,使用TransformerDecoder类调用解码器层、解码器层数、归一化等创建解码器
- d_model,模型维度
- nhead,多头注意力的头数
9.3 前向传播
def forward(self, src, mask, query_embed, pos_embed):bs, c, h, w = src.shapesrc = src.flatten(2).permute(2, 0, 1)pos_embed = pos_embed.flatten(2).permute(2, 0, 1)query_embed = query_embed.unsqueeze(1).repeat(1, bs, 1)mask = mask.flatten(1)tgt = torch.zeros_like(query_embed)memory = self.encoder(src, src_key_padding_mask=mask, pos=pos_embed)hs = self.decoder(tgt, memory, memory_key_padding_mask=mask,pos=pos_embed, query_pos=query_embed)return hs.transpose(1, 2), memory.permute(1, 2, 0).view(bs, c, h, w)
- 前向传播函数,传入数据源、掩码、Q向量、位置编码等
- bs, c, h, w,[2, 256, 24, 24],获取数据源的维度,batch、通道数、长、宽,每次传入的数据的长宽可能不同
- src,torch.Size([576, 2, 256]),维度从[batch_size, channels, height, width]转换为[height*width, batch_size, channels]
- pos_embed ,torch.Size([576, 2, 256]),位置编码进行同样操作
- query_embed ,torch.Size([100, 2, 256]),将Q向量扩展并重复,以匹配batch_size
- mask ,torch.Size([2, 576]),展平减少一个维度
- tgt ,torch.Size([100, 2, 256]),初始化目标序列tgt为与Q向量维度相同但全为0的Tensor,这在解码器的自回归预测中用作初始输入
- memory ,torch.Size([576, 2, 256]),调用编码器传入数据源、掩码、位置编码得到输出
- hs ,torch.Size([6, 100, 2, 256]),调用解码器传入初始化目标序列、编码器输出、掩码、位置编码、Q向量等得到输出
- return ,hs:torch.Size([6, 2, 100, 256]),memory:torch.Size([2, 256, 24, 24]),将编码器输出和解码器的输出的维度进行调整后返回