写在前面:
对于BEVFormer算法框架的整体理解,大家可以找到大量的资料参考,但是对于算法代码的解读缺乏详实的资料。因此,本系列的目的是结合代码实现细节、在tensor维度的变换中帮助读者对算法能有更直观的认识。
本系列我们将对BEVFormer公版代码(开源算法)进行逐行解析,以结合代码理解Bevformer原理,掌握算法细节,帮助读者们利用该算法框架开发感知算法。在本系列的最后笔者还将面向地平线的用户,指出地平线参考算法在开源算法基础上做出的修改及修改背后的考虑,在算法部署过程中为用户提供参考。
公版代码目录封装较好,且以注册器的方式调用模型,各个模块的调用关系可以从configs/bevformer中的config文件中清晰体现,我们以bevformer_tiny.py为例3解析代码,Encoder部分已经发出,见《BEVFormer开源算法逐行解析(一):Encoder部分》,本文主要关注BEVFormer的Decoder和Det部分。
对代码的解析和理解主要体现在代码注释中。
1 PerceptionTransformer:
功能:
将encoder层输出的bev_embed传入decoder中
将在BEVFormer中定义的query_embedding按通道拆分成通道数相同的query_pos和query,并传入decoder中;
利用query_pos通过线性层reference_points生成reference_points,并传入decoder;该reference_points在decoder中的CustimMSDeformableAttention作为融合bev_embed的基准采样点,作用类似于two-stage目标检测中的Region Proposal ;
返回inter_states, inter_references给cls_branches和reg_branches分支得到目标的种类和bboxes。
解析:
2 DetectionTransformerDecoder
功能:
循环进入6个相同的DetrTransformerDecoderLayer,一个DetrTransformerDecoderLayer包含 ('self_attn', 'norm', 'cross_attn', 'norm', 'ffn', 'norm'),每层输出output和reference_points;
在6层DetrTransformerDecoderLayer遍历完成后,将6层输出的output和reference_points输出。
解析:
深色代码部分生成的reference_points结构见下图,其中inverse_sigmoid(pt_reference_points)即为reference_points/Linear(query_pos)

2.1 MultiheadAttention
功能:
object_query的多头自注意力机制,如下图所示。

解析:
2.2 CustomMSDeformableAttention
功能:
利用可变形注意力机制将encoder模块输出的bev_embed融入object_query,如下图所示;
输出该层的output,将其作为下一层DetrTransformerDecoderLayer的输入,并利用该层output生成该层对应的reference_points。

解析:
3 cls_branches&®_branches
功能:
利用decoder输出的bev_embed, inter_states(6层输出的outs), init_reference_out(由query_pos生成的初始reference_points), inter_references_out(6层输出的reference_points)生成目标类别和bboxes;
生成包含bev_embed、 all_cls_scores、all_bbox_preds在内的outs,其中 all_cls_scores、all_bbox_preds用于计算Loss、梯度回传;bev_embed可用于segmentation等任务,进行BEV视角下的语义分割。
解析:
深色代码部分生成的tmp[0:2]和tmp[4:5]结构见下图,实质上就是"DetectionTransformerDecoder"中生成的reference_points。

结语:
至此,BEVFormer中的Encoder和Decoder部分的逐行代码解析就完成了,如果后续有需求也可以再出一期关于解析Loss计算的文档,这部分比较基础,有兴趣的同学也可以先结合源码自学。

