该示例为参考算法,仅作为在J6上模型部署的设计参考,非量产算法
简介
BEVFormer是当前热门的自动驾驶系统中的3D视觉感知任务模型。BEVFormer是一个端到端的框架,BEVFormer可以直接从原始图像数据生成BEV特征,无需依赖于传统的图像处理流程。它通过利用Transformer架构和注意力机制,有效地从多摄像头图像中学习生成高质量的鸟瞰图(Bird'sEyeView, BEV)特征表示。相较于其他的BEV转换方式:
时空注意力机制:模型结合了空间交叉注意力(Spatial CrossAttention, SCA)和时间自注意力(Temporal SelfAttention, TSA),使网络能够同时考虑空间和时间维度上的信息。融合历史bev特征来提升预设的BEV空间中的query的自学能力,得到bev特征。
**Deformable attn:**通过对每个目标生成几个采样点和采样点的offset来提取采样点周围的重要特征,即只关注和目标相关的特征,减少计算量。
**transformer架构:**能够有效捕捉序列中的长期依赖关系,适用于处理图像序列。
性能精度指标
模型参数:
模型 | 数据集 | Input shape | backbone | bevsize | encoder layers |
|---|
BEVFormer | Nuscenes | 480x800 | resnet50 | 50x50 | 3 |
性能精度表现:
J6E性能 FPS | 检测精度浮点/定点 | |
|---|
| NDS | mAP |
2048 | 03713/03678 | 02673/02615 |
模型介绍

公版BEVFormer模型主要可以分为以下几个关键部分:
Backbone网络:用于从多视角摄像头图像中提取特征,本文为tiny版本,因此为ResNet50。
时空特征提取:BEVFormer通过引入时间和空间特征来学习BEV特征。具体来说,模型包括:
Deformable Attention(可变形注意力):BEVFormer使用可变形注意力机制来加速运算,提高模型对不同视角图像特征的适应性。
BEV特征生成:通过时空特征的融合,完成环视图像特征向 BEV 特征的建模。
Decoder:设计用于3D物体检测的端到端网络结构,基于2D检测器Deformable DETR进行改进,以适应3D空间的检测任务。
Encoder
heal/models/task_modules/bevformer/encoder.py
包含selfattention、crossattention、ffn:
其中Encoder层的参数为:
代码:heal/models/task_modules/bevformer/view_transformer.py
bevquery:bevhbevw,256
定义了一组长度为HW (tiny为50x50)的BEV queries。对应自车周围的范围。
bevpos: bs, embeddims, bevh, bevw,用于对query添加位置编码
positionalencoding为可学习的位置编码方式,通过nnEmbedding生成坐标编码
prevbev:
上一帧的bevfeature(encoder层输出),可以是多时间序列。生成过程和当前BEV相同。具体实现在get_prev_bev。此时需要对上一时刻的 BEV 特征与当前时刻做空间上的对齐然后使用gridsample采样得到prevbev
最后需要融合query,value=prevbev,bevquery
hybirdref2d
根据bevh, bevw生成二维坐标系中的点坐标ref2d
referencepointscam:生成Camera的referencepoints
pointsampling为3D坐标到2D图像平面的转换。为了筛选有效query公版使用了bevmask,地平线版本考虑到目前不支持动态部署,因此不做筛选。
key,Value:多层级的图像特征featuremap
spatialshapes:为多尺度特征所对应的h,w
Temporal SelfAttention 模块
Temporal SelfAttention 模块为自注意力,提取了前一个时刻的BEV特征作为先验知识来提高 BEV Query 的建模能力,相比于直接初始query来说融合历史的bev特征更能提高 BEV Query 的建模能力。
注意力计算方式和公版一致,在此不做过多介绍。代码路径:heal/models/base_modules/bevformer_attention.py HorizonTemporalSelfAttention
Deformable SelfAttention 模块
不同于global atten,deformable self atten通过生成采样点和采样点的周围需要关注的4个点samplelocationpointoffset,通过采样获得每一个query和其关注的4个point所对应的特征向量,然后和学习到的attetionweight做乘加,得到bevquery特征。总体见下图。

代码路径:heal/models/base_modules/bevformer_attention.py HorizonTemporalSelfAttention
**step1:**生成每个query对应的reference point 的偏移Sampling offsets:
参数Offset的计算是同时考虑了value[0]和bev_query的信息,在映射空间的维度上进行了concat
**step2:**关键区域samplinglocations 的坐标为refoffset/offsetnormalizer
**step3:**Attention weight计算:对query做linearsoftmax操作
attentionweights为linear实现:
**step4:**value计算
**step5:**做MultiScaleDeformableAttn计算
主要操作为:samplinglocations作为grid对value采样,生成samplinglocations对应的特征向量samplingvalue(每一个query和其关注的4个point所对应的特征向量),不同level的做dim=1的cat,然后samplingvalue和attentionweights做mul,得到最终输出的samplingvalue。
**step6:**将前一时刻的 bevquery 与当前时刻的 bevquery (output)做平均,最后经过一个linear
至此,Temporal SelfAttention 模块的逻辑到此结束,将生成的 bevquery 送入到后面的 Spatial CrossAttention 模块中。
Spatial CrossAttention 模块
利用 Temporal SelfAttention 模块输出的 bev_query, 对主干网络和 Neck 网络提取到的mlvl特征进行查询,生成 BEV 空间下的BEV Embedding特征;实现代码:heal/models/base_modules/bevformer_attention.py HorizonSpatialCrossAttention
该层的输入参数:
此时query为时序模块的输出output为该层的bevquery。shape为bs, numquery, embeddims
在该层主要的操作为multiscaledeformable cross attention。和TS模块相同的,需要经过Sampling offsets预测和samplinglocations 计算,以及Attention weight计算和value计算后作为参数送入deformableAttention。不同在于TS为自注意力计算,value和attentionweight为query与query之间的计算,交叉注意力层则为query和featuremap的交互。其中numpoint=8,numlevel=4(tiny为1)数量增加。
最后将六个环视相机查询到的特征整合到一起,再求一个平均值,然后经过1x1的outputprojconv
Decoder
Decoder层是获得预测框和分类得分的。包含了selfattn和fc层。
代码路径:heal/models/task_modules/bevformer_decoder/decoder.py
Layer输入参数为:
query、querypos:
初始化一组num=900的query和对应的querypos,使用nnEmbedding 生成,为可学习的。
initreferencepoints:使用nnLinearsigmoid生成,为可学习的,作为初始参考坐标(decoder实际传入前2维,refpoint会在每一层decoderlayer计算后更新)
value:为Encoder输出的bevembed
regbranches:回归层
spatialshapes:特征的h,w信息
attnmask:None
SelfAttn
自注意力计算,利用query和query_pos去做常规的 SelfAttention 运算更新query
MSDeformableAttention
heal/models/base_modules/bevformer_attention.py HorizonMultiScaleDeformableAttention
将初始的referencepoints经过sigmoid作为初始参考点坐标:
由selfattn获得的query生成samplingoffsets、samplinglocations和attentionweight,送入multiscaledeformableattn。
相同的,遍历所有level,取出不同level的采样点samplinglocations和value,然后使用gridsample得到该层level下的samplingvalue,遍历所有level后放入list中,然后与attentionweight做mul计算。
经过6层decoder后,将输出结果和referencepoints添加到list中返回decoder的结果。
将decoder层输出的interreferences送入regbranch和clsbranch预测分支预测分类和回归结果
地平线部署说明
公版bevformer在J6上部署相比于J5来说更简单了,需要考虑的因素更少。J6对非4维的支持可以和4维的同等效率,因此J6支持公版的注意力实现,不再限制维度,因此无需对维度做Reshape,可直接支持公版写法。但需注意的是公版的bevmask会导致动态shape。J6不支持动态输入,因此公版的bevmask无法使用,为了提升模型的运行性能,工具链提供了gridsample算子的替换方式。在精度上,我们修复了公版的bug已获得了精度上的提升,同时通过对关键层做int16的量化精度配置以保障1%以内的量化精度损失。
下面将部署优化对应的改动点以及量化配置依次说明。
性能优化
改动点1:
将attention层的mean替换为conv计算,使性能上获得提升。
heal/models/base_modules/bevformer_attention.py
改动点2:
公版中,在Encoder的空间融合模块,会根据bevmask计算有效的query和referencepoints,输出queriesrebatch和referencepointsrebatch,作用为减少交互的数据量,提升模型运行性能。对于稀疏的query做crossattn后再将query放回到bevfeature中。
以上提取稀疏query步骤的主要算子为gather,放回bevfeature步骤的主要算子为scatter。由于工具链对这两个算子暂未支持(gather算子930已支持)而且bevmask为动态的,为了提升模型的运行性能,工具链提供了gridsample算子的替换方式,index计算只与内外参有关,因此作为前处理,将计算好的index作为模型输入即可。
gather
gather为根据bevmask来提取稀疏query,降低cross attn的数据量,提升运行效率。
代码路径:heal/models/task_modules/bevformer/view_transformer.py
referencepointsrebatch :
queryrebatch :
scatter
scatter操作对经过deformableattention后的query放入到bevfeature中,然后求平均。
代码路径:heal/models/base_modules/bevformer_attention.py
其中restorebevgrid,根据bevmask反算回bevfeature的位置
精度优化
浮点精度
改动点3:
公版通过canbus 初始化ref来做时序融合,然而这个时候bev feat并没有对齐,在attention计算时不能简单的concat起来。因此我们换了一种时序对齐的方式,通过前后两帧的ego2global坐标系转换矩阵将当前帧的bev特征和上一帧对齐,此时ref都是一样的。(非J6不支持,为公版bug),精度上获得提升。
heal/models/task_modules/bevformer/view_transformer.py get_prev_bev get_fusion_ref
改动点4:
量化精度
为量化精度保证,我们将以下的算子配置为int16或int32输出:
**viewtransformer:**输入节点做int16量化:
**attention层:**encoder 各层的 selfattention(sa)、crossattention(ca)的 outputproj、addres 等节点,以及 ffn 的 add、ffn2 均配置为 int16 输出:
**decoder层:**各 decoder layer 的 clsbranches、regbranches、selfattention(addselfattn)、crossattention(caaddres、caoutputproj)、ffn 等节点配置为 int16 输出;同时 referencepoints、sigmoid 等节点也配置为 int16:
注:上述 int16_qconfig 字典会与 None_qconfig_template 合并后,经 ModuleNameTemplate(\..., freeze=True) 模板统一作用于 cali_qconfig_setter 与 qat_qconfig_setter 两个 QconfigSetter;其中 cali_qconfig_setter 的 reference observer 为 MSEObserver,qat_qconfig_setter 的 reference observer 为 MinMaxObserver。
总结与建议
训练建议:
部署建议:
建议bev size的选择考虑性能影响。J6相比于J5带宽增大,但仍需注意bevsize过大导致访存时间过长对性能的影响,建议考虑实际部署情况选择合适的bevsize做性能验证。
使用bevmask来提升运行性能,可参考41章节使用gridsample替换不支持的scatter。
在注意力机制中存在一些ElementWise操作,对于导致性能瓶颈的可以考虑conv替换,对于造成量化风险的可以根据敏感度分析结果合理选择更高的量化精度,以确保注意力机制的部署。
本文通过对Bevformer在地平线征程6上量化部署的优化,使得模型在该计算方案上用低于1%的量化精度损失,得到latency为5263ms的部署性能,同时,通过Bevformer的部署经验,可以推广到其他模型部署优化,例如包含MSD模型结构、transformerbased BEV的部署。
附录
modellabs官网:https://(待发布)
参考文档使用指南:https:///github/heal/readmemd(待发布)