专栏感知地平线静态目标检测 MapTR 参考算法-V2.0

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

芯链情报局2024-08-31
2319
3

该示例为参考算法,仅作为在J6上模型部署的设计参考,非量产算法

简介

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

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

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

性能精度指标

模型配置:

模型

数据集

Epoch

Image shape

Backbone

View Transformer

BEV Size

maptroe_henet_tinym_bevformer_nuscenes

NuScenes

24

6x3x480x800

HENet_Tinym

Bevformer

100x50

maptrv2_resnet50_bevformer_nuscenes

NuScenes

24

6x3x480x800

ResNet50

Bevformer

100x50

性能精度表现:

模型

性能FPS(单核)

检测精度mAP(浮点/定点)

量化配置

maptroe_henet_tinym_bevformer_nuscenes

J6E:67.54

0.6632/0.6387(精度保持率96.31%)

默认int8模板

maptrv2_resnet50_bevformer_nuscenes

J6E:26.68

0.5859/0.5763(精度保持率98.36%)

Top30 Int16

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

  2. maptrv2_resnet50_bevformer_nuscenes默认使用Lidar坐标系,和公版保持一致,同时适配ego坐标系;maptroe_henet_tinym_bevformer_nuscenes默认使用ego坐标系,增加了sdmap的输入融合;

  3. 量化配置TopK:前K个量化敏感的算子;默认int8模板:与grid相关算子设置int16,其他均设置int8

公版模型介绍

MapTR

公版MapTR模型结构
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。

MapTRv2

公版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数据集上的指标。

地平线部署说明

地平线参考算法使用流程请参考J6参考算法使用指南;对应高效模型设计建议请参考《J6平台算法设计建议》
MapTROE模型引入了SD map的前融合结构,与图像视角转换后的bev feature进行融合,再通过优化后的MapTR head生成矢量化的地图元素。整体结构如下:
MapTROE
因此maptroe_henet_tinym_bevformer_nuscenes模型相比之前版本新增了如下优化点:
  • 引入SD map前融合,提升模型整体精度表现(精度指标提升7+);

  • MapTR Head部分优化为Instance Head,在精度相当的情况下性能提升35%;

  • 采用J6芯片高效backbone HENet_tinym,在精度轻微提升的情况下极大提高了性能;

  • View Transformer采用优化版bevformer,在精度相当的情况下提高了性能。

maptroe_henet_tinym_bevformer_nuscenes模型对应的代码路径:

模块

代码路径

Config

{oe_path}/samples/ai_toolchain/horizon_model_train_sample/scripts/configs/map/maptroe_henet_tinym_bevformer_nuscenes.py

Model Structure

/usr/local/lib/python3.10/dist-packages/hat/models/structures/maptr/maptroe.py: class MapTROE(nn.Module)

Backbone

/usr/local/lib/python3.10/dist-packages/hat/models/backbones/henet.py: class HENet(nn.Module)

Neck

/usr/local/lib/python3.10/dist-packages/hat/models/necks/fpn.py: class FPN(nn.Module)

View Transformer

/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/bevformer/view_transformer.py: class SingleBevFormerViewTransformer(BevFormerViewTransformer)其中包含的BEV Encoder模块:/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/bevformer/encoder.py: class SingleBEVFormerEncoder(BEVFormerEncoder)

OSM Encoder

/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/sdmap_fusion.py: class ConvDown(nn.Module)

BEV Fusion

/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/sdmap_fusion.py: class MapFusion(nn.Module)

BEV Decoder

/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/instance_decoder.py: class MapInstanceDetectorHead(nn.Module)

Criterion

/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/criterion.py: class MapTRCriterion(nn.Module)其中的Assigner模块:/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/assigner.py: class MapTRAssigner(nn.Module)

Post Process

/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/postprocess.py: class MapTRPostProcess(nn.Module)

性能优化

Backbone

MapTROE采用基于J6芯片的高效轻量化Backbone HENet_TinyM(Hybrid Efficient Network, Tiny for J6M),HENet能更好地利用征程6系列芯片的算力,在模型精度和性能上更具优势。HENet_TinyM采用了纯CNN架构,总体分为四个stage,每个stage会进行一次2倍下采样,具体结构配置如下:

Neck

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

View Transformer

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

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

  2. BEV特征编码:
    a. 默认prev_bev由cur_bev改为全0;
    b. 取消can_bus信息的使用,前一帧bev特征prev_bev和当前帧cur_bev的对齐方式由使用can_bus信息正向校准改为使用GridSample算子反向采样校准;
    c. 取消了bev_query初始化部分和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
...

e. 支持公版Bevformer中的bev_mask,并将涉及到的gather/scatter操作,用gridsample等价替换,提高模型速度。

Head

公版MapTR使用分层query机制,定义一组instance queries和由所有instance共享的point queries,每个地图元素对应一组分层query(一个instance query和共享的point queries广播相加得到),在decoder layer中分别使用self-attention和cross-attention来更新分层query。

MapTROE的改进则是为每个地图元素分配一个instance query(无直接point query),每个query用于编码语义信息和地理位置信息,decoder阶段和公版MapTR一样,分别进行multi-head self-attention和deformable cross-attention,最后每个instance query通过MLP网络生成类别信息和元素内的点集坐标,相比公版预测分层query,改进后直接预测instance query带来的计算量更少,极大地提高了模型在端侧的运行性能。同时借鉴StreamMapNet,使用多点注意力方法来适应高度不规则的地图元素,扩大感知范围。代码见/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/maptr/instance_decoder.py: class MapInstanceDetectorHead(nn.Module)

多点注意力

多点注意力
传统的可变形注意力为每个query分配一个参考点,多点注意力则使用前一层预测的地图元素的多个点作为当前层query的参考点,具体计算方式是在点维度上扩展了一层求和,将一个点变成多个点,分别计算deformable attention。回归的时候并非预测offsets,而是直接预测地图元素点的坐标位置。

Attention

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

精度优化

浮点精度

MapTROE模型引入SD Map前融合,与图像转换后的bev feature进行融合,以提高在线地图的生成质量。模块结构如下图所示:
SDMap

SD Map特征提取

SD Map从OpenStreetMap(OSM)中获取,通过由GPS提供的车辆位姿,查询车辆当前位姿附近的SD Map,然后将SD Map转换到自车坐标系下,与NuScenes中的数据标注坐标系保持一致。SD Map会从车道中心骨架线Polyline的形式转化为栅格结构,大小和BEV特征相同,经过CNN变成特征图,对应SD Map的先验信息。

SD Map特征融合

栅格化后的SD Map和实际场景可能会出现错位、不对齐的情况,这种错位导致直接Concatenate BEV特征和SD Map特征的效果并不好,为了解决这个问题,引入了特征融合模块,通过网络学习来决定最适合的对齐方式,可以有效地利用SD Map先验提升BEV特征的效果。关于特征融合模块,分别实验了交叉注意力与CNN网络,通过精度与性能的平衡,最后选择了CNN 网络模块。

量化精度

  1. maptroe_henet_tinym_bevformer_nuscenes模型默认使用int8模板,也即与grid相关算子设置int16,其他均设置int8,相比maptrv2_resnet50_bevformer_nuscenes的量化配置,int16量化的算子更少,模型端侧性能更高

  2. 浮点阶段采用更大的weight decay训练,使浮点数据分布范围更小,浮点模型参数更有利于量化

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

  4. 取消了公版模型MapTRHead中对于量化不友好的inverse_sigmoid操作;此外MapTROE对Head的优化无需再引入reg_branches输出和reference相加后再sigmoid的操作:

地平线参考算法

class MapInstanceDetectorHead(nn.Module):
...
def get_outputs(...):
...
for lvl in range(len(outputs_classes)):
tmp = reference_out[lvl].float()
感知
征程6
+3
评论2
0/600
  • 默认26688
    Lv.1

    目前只看到maptroe的config文件,maptrv2的文件哪里可以提供。

    2024-12-02
    2
    0
  • Luke
    Lv.1
    从osm上下载的四个地区的.osm文件,经过qgis转换为.shp后,报错sd_map["type"]不在
    options = [ "trunk", "primary", "secondary", "tertiary", "unclassified", "residential", "trunk_link", "primary_link", "secondary_link", "tertiary_link" "living_street", "road", ] 这几类内。
    请问SD-map的数据应该如何获取?
    2025-11-28
    0
    1
    • 槿依琳回复Luke:

      +1

      2026-01-23
      0