写点什么

地平线静态目标检测 MapTR 参考算法 -V1.0

  • 2024-09-27
    广东
  • 本文字数:5847 字

    阅读完需:约 19 分钟

地平线静态目标检测 MapTR 参考算法-V1.0

1.简介

高清地图是自动驾驶系统的重要组件,提供精确的驾驶环境信息和道路语义信息。传统离线地图构建方法成本高,维护复杂,使得依赖车载传感器的实时感知建图成为新趋势。早期实时建图方法存在局限性,如处理复杂地图元素的能力不足、缺乏实例级信息等,在实时性和后处理复杂度上存在挑战。


为了解决这些问题,基于 Transformer 的 MapTR 模型被提出,它采用端到端结构,仅使用图像数据就能实现高精度建图,同时保证实时性和鲁棒性。MapTRv2 在此基础上增加了新特性,进一步提升了建图精度和性能。


地平线面向智驾场景推出的 征程 6 系列(J6)芯片,在提供强大算力的同时带来了极致的性价比,征程 6 芯片对于 Transformer 模型的高效支持助力了 MapTR 系列模型的端侧部署。本文将详细介绍地平线算法工具链在 征程 6 芯片部署 MapTR 系列模型所做的优化以及模型端侧的表现。

2.性能精度指标

模型配置:


模型数据集



性能精度表现:



  1. 预测的地图元素:“divider”,“ped_crossing”,“boundary”;

  2. 默认使用 Lidar 坐标系,和公版保持一致。同时适配 ego 坐标系;

  3. 量化配置 TopK:前 K 个量化敏感的算子。


3.公版模型介绍

3.1MapTR


MapTR 模型的默认输入是车载摄像头采集到的 6 张相同分辨率的环视图像,使用 nuScenes 数据集,同时也支持拓展为多模态输入例如雷达点云。模型输出是矢量化的地图元素信息,其中地图元素为人行横道、车道分隔线和道路边界 3 种。模型主体采用 encoder-decoder 的端到端结构:


  • Map Encoder 通过 CNN Backbone+BEV Encoder 负责提取 2D 图像特征并转换到统一的 BEV 视角。MapTR-nano 默认使用 ResNet18 作为 Backbone,MapTR-tiny 默认使用 ResNet50。MapTR 兼容多种 BEV Encoder 实现方式例如 GKT、LSS 和 IPM 等并且表现稳定,鉴于 GKT 的部署高效性以及在消融实验中的精度表现更好,公版 MapTR 使用 GKT 作为默认 BEV Encoder 实现方式。

  • Map Decoder 采用 Hierarchical Query Embedding Scheme,即从 point-level(位置)和 instance-level(轮廓)显式地编码地图元素,point-level queries 被所有 instances 共享并融合进 instance-level queries 从而生成 hierarchical queries,hierarchical queries 经过级联的 decoder layers(默认是 6 层)不断更新。每个 decoder layer 首先使用多头自注意力(MHSA)做 inter-instance 和 intra-instance 的信息交互,接着会使用 Deformable Attention 来与 Map Encoder 输出的 BEV 特征做信息交互。point-level 的信息被所有 instance 共享,所以对于每个 instance 而言,映射到 BEV 空间的多个参考点 reference points 是灵活且动态分布的,这对于提取 long-range context information 预测随机形状的地图元素是有益的。

  • MapTR Head 由分类分支和回归分支构成。分类分支预测 instances 的类别,回归分支预测 points 集合的位置。Head 输出的预测值和真值 GT 之间采用 Hierarchical Bipartite Matching 实现监督学习,分为 Instance-level Matching 和 Point-level Matching,因此损失函数为三个部分的加权和:分类 Classification Loss、点对点位置 Point2point Loss 和连接边方向 Edge Direction Loss。

3.2 MapTRv2



MapTRv2 在 MapTR 的基础上增加了新的特性:


  1. 针对层次化 query,引入解耦自注意力,极大地减少了计算量和显存消耗;对于和输入特征交互的 cross-attention 部分,则引入了 BEV、PV 和 BEV+PV 三种变体;

  2. 引入辅助 one-to-many 集合预测分支,增加了正样本数,加速了训练收敛;

  3. 引入辅助 dense supervision,引入深度估计预测头、PV 和 BEV 视角下的分割头,进一步提升模型精度。由于引入深度信息做监督学习,为了显式地提取深度信息,公版 MapTRv2 选择基于 LSS 的 BEVPoolv2 来作为 BEV 视角转换方式;

  4. 引入新的地图元素车道中心线(centerline);

  5. 增加 3D 地图元素预测能力,并提供 Argoverse2 数据集上的指标。


4.地平线部署说明

地平线参考算法使用流程请参考附录《TCJ6007-J6 参考算法使用指南》;对应高效模型设计建议请参考附录《TCJ6005-J6 平台算法设计建议》


模型对应的代码路径:


4.1 性能优化

Neck

Neck 部分采用了地平线内部实现的 FPN,相比公版 FPN 实现,在 征程 6 平台上性能更加友好。

View Transformer

地平线参考算法版本将基于 LSS 的视角转换方式替换为 Bevformer 的 View Transformer 部分。


  1. BEV Grid 尺寸:对于 Dense BEV 而言,BEV Grid 的尺寸大小实际地影响模型性能。征程 6 平台增强了带宽能力,但仍需注意 BEV 网格过大导致访存压力过大而对性能带来负面影响,建议考虑实际部署情况选择合适的 BEV 网格大小来设计模型。相比公版 MapTRv2 模型使用 200x100 的网格,地平线部署模型使用 100x50 的网格来实现性能和精度的平衡。

  2. BEV 特征编码:

  3. 默认 prev_bev 由 cur_bev 改为全 0;

  4. 取消 can_bus 信息的使用,前一帧 bev 特征 prev_bev 和当前帧 cur_bev 的对齐方式由使用 can_bus 信息正向校准改为使用 GridSample 算子反向采样校准;

  5. 取消了 bev_query 初始化部分和 can_bus 的融合;

  6. 取消了公版的 TemporalSelfAttention,改为 HorizonMSDeformableAttention,提升速度。


公版模型class MapTRPerceptionTransformer(BaseModule):    ...    def attn_bev_encode(...):        ...        if prev_bev is not None:            if prev_bev.shape[1] == bev_h * bev_w:                prev_bev = prev_bev.permute(1, 0, 2)            if self.rotate_prev_bev:                for i in range(bs):                    # num_prev_bev = prev_bev.size(1)                    rotation_angle = kwargs['img_metas'][i]['can_bus'][-1]                    tmp_prev_bev = prev_bev[:, i].reshape(                        bev_h, bev_w, -1).permute(2, 0, 1)                    tmp_prev_bev = rotate(tmp_prev_bev, rotation_angle,                                          center=self.rotate_center)                    tmp_prev_bev = tmp_prev_bev.permute(1, 2, 0).reshape(                        bev_h * bev_w, 1, -1)                    prev_bev[:, i] = tmp_prev_bev[:, 0]
# add can bus signals can_bus = bev_queries.new_tensor( [each['can_bus'] for each in kwargs['img_metas']]) # [:, :] can_bus = self.can_bus_mlp(can_bus[:, :self.len_can_bus])[None, :, :] bev_queries = bev_queries + can_bus * self.use_can_bus ...地平线参考算法class BevFormerViewTransformer(nn.Module): ... def __init__(...): ... self.prev_frame_info = { "prev_bev": None, "scene_token": None, "ego2global": None, } ... def get_prev_bev(...): if idx == self.queue_length - 1 and self.queue_length != 1: prev_bev = torch.zeros( (bs, self.bev_h * self.bev_w, self.embed_dims), dtype=torch.float32, device=device, ) ... else: prev_bev = self.prev_frame_info["prev_bev"] if prev_bev is None: prev_bev = torch.zeros( (bs, self.bev_h * self.bev_w, self.embed_dims), dtype=torch.float32, device=device, ) # 对应改动 2.a ... def bev_encoder(...): ... tmp_prev_bev = prev_bev.reshape( bs, self.bev_h, self.bev_w, self.embed_dims ).permute(0, 3, 1, 2) prev_bev = F.grid_sample( tmp_prev_bev, norm_coords, "bilinear", "zeros", True ) # 对应改动 2.b ...class SingleBevFormerViewTransformer(BevFormerViewTransformer): ... def get_bev_embed(...): ... bev_query = self.bev_embedding.weight bev_query = bev_query.unsqueeze(1).repeat(1, bs, 1) # 对应改动 2.c ...公版模型 Configmodel = dict( ... pts_bbox_head=dict( type='MapTRHead', ... transformer=dict( type='MapTRPerceptionTransformer', ... encoder=dict( type='BEVFormerEncoder', ... transformerlayers=dict( type='BEVFormerLayer', attn_cfgs=[ dict( type='TemporalSelfAttention', embed_dims=_dim_, num_levels=1), ... ]地平线参考算法 Configmodel = dict( ... view_transformer=dict( type="SingleBevFormerViewTransformer", ... encoder=dict( type="SingleBEVFormerEncoder", ... encoder_layer=dict( type="SingleBEVFormerEncoderLayer", ... selfattention=dict( type="HorizonMSDeformableAttention", # 对应改动 2.d ... ), ) ) ))
复制代码

Attention

模型中用到的 attention 操作均使用地平线提供的算子,相比 PyTorch 提供的公版算子,地平线 attention 算子在保持算子逻辑等价的同时在效率上进行了优化


from hat.models.task_modules.bevformer.attention import (    HorizonMSDeformableAttention,    HorizonMSDeformableAttention3D,    HorizonSpatialCrossAttention,)
复制代码

4.2 精度优化

量化精度

  1. 对模型中量化敏感的 Top30 个算子采用 Int16 精度量化:


Config 文件if os.path.exists(pts_path):    pts_table = torch.load(pts_path)    cali_qconfig_setter = (        sensitive_op_calibration_8bit_weight_16bit_act_qconfig_setter(            pts_table,            topk=30,            ratio=None,        ),        default_calibration_qconfig_setter,    qat_qconfig_setter = (        sensitive_op_qat_8bit_weight_16bit_fixed_act_qconfig_setter(            pts_table,            topk=30,            ratio=None,        ),        default_qat_fixed_act_qconfig_setter,
复制代码


  1. QAT 训练采用固定较小的 learning rate 来 fine-tune,这里固定也即取消 LrUpdater Callback 的使用,配置如下:


Config 文件float_lr = 6e-4qat_lr = 1e-6
复制代码


2.取消了公版模型 MapTRHead 中对于量化不友好的 inverse_sigmoid 操作;此外部署模型取消了 MapTRHead 中 reg_branches 输出和 reference 相加后再 sigmoid 的操作(该操作可以转移到部署后处理中完成):


公版模型class MapTRHead(DETRHead):    ...    def forward(...):        ...        for lvl in range(hs.shape[0]):            if lvl == 0:                # import pdb;pdb.set_trace()                reference = init_reference            else:                reference = inter_references[lvl - 1]            reference = inverse_sigmoid(reference)            ...            tmp = self.reg_branches[lvl](...)            tmp[..., 0:2] += reference[..., 0:2]            tmp = tmp.sigmoid() # cx,cy,w,h            地平线参考算法class MapTRPerceptionDecoderv2(nn.Module):    ...    def get_outputs(...):        ...        for lvl in range(len(outputs_classes)):            reference = reference_out[lvl].float()            # reference = inverse_sigmoid(reference)            ...            tmp = bbox_outputs[lvl].float()            tmp[..., 0:2] += reference[..., 0:2]            tmp = tmp.sigmoid()    ...
def forward(...): outputs = self.bev_decoder(...) if self.is_deploy: return outputs ... outputs = self.get_outputs(...) ... return self._post_process(data, outputs)
复制代码

4.3 其他优化

设计优化

  1. 在 View Transformer,使用 Bevformer 替换地平线支持不友好的公版 MapTRv2 基于 LSS 的 BEVPoolv2 来作为 PV 视角转 BEV 视角的方式;

  2. 在 View Transformer 的 BEV Encoder 模块取消了 BEV 特征的时序融合,也取消了 Bevformer 时序自注意力模块,模型整体精度不低于公版基于 Bevformer 的精度。


5. 总结与建议

5.1 部署建议

  1. 遵循硬件对齐规则,一般的 tensor shape 对齐到 2 的幂次,conv-like 的算子 H 维度对齐到 8、W 维度对齐到 16、C 维度对齐到 32,若设计尺寸不满足对齐规则时会对 tensor 自动进行 padding,造成无效的算力浪费;

  2. 合理选择 BEV Grid 尺寸,征程 6 平台的带宽得到增强,但仍需考虑 BEV Grid 尺寸对模型性能的影响,并且综合衡量模型精度预期,选择合适的 BEV Grid 尺寸以获得模型性能和精度的平衡;

  3. 优先选择 征程 6 平台高效 Backbone 来搭建模型,高效 Backbone 经过在 征程 6 平台的反复优化和验证,相比其他 Backbone 的选择,在性能和精度上可以同时取得出众的效果,因此选取 征程 6 平台高效 Backbone 来搭建模型可以对整个场景模型带来性能和精度的增益。

5.2 总结

本文通过对 MapTRv2 进行地平线量化部署的优化,使得模型在 征程 6 计算平台上用较低的量化精度损失,获得单核 26.66 FPS 的部署性能。同时,MapTRv2 的部署经验可以推广到其他相似结构或相似使用场景模型的部署中。


对于地平线 MapTR 参考算法模型,Backbone 和 BEV 中融合方式等的优化仍在探索和实践中,Stay Tuned!


6. 附录

  1. 公版论文:MapTR

  2. 公版模型源码:GitHub-MapTR


用户头像

还未添加个人签名 2021-03-11 加入

还未添加个人简介

评论

发布
暂无评论
地平线静态目标检测 MapTR 参考算法-V1.0_自动驾驶_地平线智能驾驶开发者_InfoQ写作社区