🚩🚩🚩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
- 继承PyTorch的nn.Module
- 构造函数,传入以下6个参数:
- d_model:模型维度
- nhead:多头注意力的头数
- dim_feedforward:MLP全连接的输出维度
- dropout:涉及到全连接层dropout比率
- activation:激活函数
- normalize_before:归一化是在Attention和MLP之间进行还是在MLP之后进行
- 初始化
- self_attn ,创建一个torch.nn的多头自注意力模块
- linear1 ,MLP的第1个全连接层
- dropout ,定义一层dropout
- linear2 ,MLP的第2个全连接层
- norm1 ,Attention层输出的层归一化
- norm2 ,MLP输出的层归一化
- dropout1 , Attention层输出的dropout
- dropout2 ,MLP输出的dropout
- activation ,使用一个辅助函数定义激活函数
- 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)
- 前向传播函数
- self.normalize_before为true
- 使用forward_pre函数进行前向传播
- 否则使用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
- 可选的前向传播函数,传入源数据src、可选的掩码src_mask、可选的填充掩码src_key_padding_mask和可选的位置编码pos
- q,k,torch.Size([725, 2, 256]),把数据源和位置编码相加生成q和k,725是序列长度、2是batch、256是每个向量维度
- src2 ,torch.Size([725, 2, 256]),调用多头自注意力模块,传入q、k、v向量,以及可选的注意力掩码和填充掩码,v就是backbone生成的特征图再转换的序列
- src ,torch.Size([725, 2, 256]),将注意力模块的输出经过dropout后与原始输入相加,实现残差连接
- src ,torch.Size([725, 2, 256]),经过一个层归一化
- src2 ,torch.Size([725, 2, 256]),相当于实现一个MLP,上一层的输出src 按照顺序先后经过:第1个全连接层、激活函数、Dropout、第2个全连接层,在第2个全连接层维度变回725
- src ,torch.Size([725, 2, 256]),将MLP的输出经过dropout后与原始输入相加,实现残差连接
- torch.Size([725, 2, 256]),经过一个层归一化
- 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
- 继承nn.Module的类
- 构造函数,传入3个参数:encoder_layer单个编码器层、num_layers编码器层堆叠的数量、norm可选的归一化模块
- 初始化
- 使用_get_clones辅助函数,传入2两个参数,堆叠所有的编码器层
- num_layers
- norm
- 前向传播函数,传入4个参数:src图像序列、mask可选的掩码、src_key_padding_mask可选的填充掩码、pos可选的位置编码
- output ,torch.Size([725, 2, 256])
- 循环遍历所有堆叠的编码器层
- output ,torch.Size([725, 2, 256]),传入当前的输出output、掩码和位置编码,每层的输出会更新output,供下一层使用
- 是否需要进行归一化
- output,torch.Size([725, 2, 256]),经过一个层归一化
- 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(训练函数/损失函数)