0 概述
该示例为参考算法,仅作为在J5上模型部署的设计参考,非量产算法
1 性能精度指标
数据集 | img_shape | Stage 1 | grid_size | num_points | Stage 2 | ||
|---|---|---|---|---|---|---|---|
Nuscenes | 256x704 | Backbone | Neck | 128x128 | 10 | Backbone | Neck |
efficientnetb0 | fastscnn | efficientnetb0 | bifpn | ||||
注:目前 grid_sample的input_feature H,W ∈ [1, 1024] 且 H* W ≤ 720*1024
性能精度表现:
性能(FPS/单核) 分割精度(浮点/定点)iou 检测精度(浮点/定点) divider ped_crossing Boundary Others NDS mAP 138 46.55/47.45 27.91/ 28.44 47.06/ 46.03 85.59/ 84.49 0.3009/ 0.2990 0.2065/ 0.2066
2 模型介绍
2.1 模型框架

Part1—2D Image Encoder:图像特征提取层。使用2D主干网络(efficientnet)和FastSCNN输出不同分辨率的特征图。返回最后一层--下采样至1/16原图大小层,用于下一步投影至3D 坐标系中。
Part2—View transformer:将img_encoder_feature生成深度特征,将深度特征和img_encoder_feature 做bev 空间转换后生成视锥点云特征。
Part3—Bev transforms:对bev特征做数据增强,仅发生在训练阶段。
Part4—3D BEV Encoder:BEV特征提取层。
Part5—BEV Decoder:分为Detection Head和Segmentation Head。得到统一的BEV特征后,使用DepthwiseSeparableFCNHead进行bev分割,分割种类为["others", "divider", "ped_crossing", "Boundary"]。使用DepthwiseSeparableCenterPointHead进行3D目标检测任务,检测的类别为["car","truck","bus","barrier","bicycle","pedestrian"]。
1.2 源码说明
Config文件
model = dict(
type="ViewFusion",
backbone=dict(
type="efficientnet",
model_type="b0",
...
),
neck=dict(
type="FastSCNNNeck",
...
),
view_transformer=dict(
type="LSSTransformer", #lss transform
...
)
bev_transforms=[...],
bev_encoder=dict(
type="BevEncoder",
...
),
bev_decoders=[
dict(
type="BevSegDecoder",
...
),
dict(
type="BevDetDecoder",
...
)
],
)
...
# 数据加载
data_loader = dict(
type=torch.utils.data.DataLoader,
...
)
float_trainer=dict(...)
calibration_trainer=dict(...)
int_trainer=dict(...)
#精度验证阶段配置
float_predictor=dict(...)
calibration_predictor=dict(...)
int_predictor=dict(...)
#编译配置
compile_cfg = dict(
march=march,
...
)
注: 如果需要复现精度,config中的训练策略最好不要修改,否则可能会有意外的训练情况出现。
img_encoder
来自6个view的image作为输入通过共享的backbone(efficientnet)和neck(FastSCNN)输出经过encoder后的feature,feature_shape为(6*B,C,1/16H,1/16W)。encoder即对多个view的img_feature 做特征提取,过程见下图:

view_transformer
bev_mt_lss 使用的转换方法是LSS实现,流程如下图所示:

LSSTransformer。可将bev_mt_lss的view_transformer分为3个部分:
生成深度特征
对深度特征和img_encoder_feature做bev坐标转换
生成视锥点云特征(frustum features)
接下来将对这三个部分做具体介绍的具体代码实现:
生成depth为60的depth_feature,对depth_feature计算深度的score值。
对应代码:
为了减少mul计算量, 先把深度特征和 feature 分开做bev视角转换:

生成点云特征

为了不遗失坐落在相同voxel中的点云特征,将对每个voxel都采样10次,最终将每个点云特征相加得到128x128x64的BEV特征图:
bev transform
bev的数据增强仅发生在训练过程中,在 BEV 下做了 rotate的数据增强,作用域是 view transformer 的输出。配置如下:
bev_encoder
bev_encoder过程是对bev_feature 做特征提取的过程,backbone为efficientnet-b0,neck为BiFPN。流程见下图:

bev_head
本模型的分割头为DepthwiseSeparableFCNHead, conv为SeparableConvModule2d
对应代码:hat/models/task_modules/fcn/head.py
def __init__(self,...):
...
def forward(self, inputs: List[torch.Tensor]):
x = inputs[self.input_index]
x = self.convs(x)
if self.dropout:
x = self.dropout(x)
seg_pred = self.cls_seg(x)
if self.training:
if self.upsample_output_scale:
seg_pred = self.resize(seg_pred)
if self.argmax_output:
seg_pred = seg_pred.argmax(dim=1)
if self.dequant_output:
seg_pred = self.dequant(seg_pred)
return seg_pred
检测为多task检测,主要分为:
在Nuscenes数据集中,目标的类别一共被分为了6个大类,网络给每一个类都分配了一个head,装在headlist中,而每个head内部都为预测的参数。
对应代码:hat/models/task_modules/centerpoint/head.py
def __init__(self,...):
self.shared_conv = nn.Sequential(
*(
self._make_conv(
in_channels=in_channels if i == 0 else share_conv_channels,
...
)
for i in range(share_conv_num)
)
)
#head module
for num_cls in num_classes:
heads = copy.deepcopy(common_heads)
heads.update({"heatmap": (num_cls, num_heatmap_convs)})
task_head = self._make_task(
...,
)
self.task_heads.append(task_head)
在hat/models/task_modules/centerpoint/head.py的TaskHead对不同的task定义conv_layers:
def __init__(...):
...
for head in self.heads:
classes, num_conv = self.heads[head]
...
#head_conv
for _ in range(num_conv - 1):
conv_layers.append(
self._make_conv(
...
)
)
c_in = head_conv_channels
#cls_layer
conv_layers.append(
ConvModule2d(
in_channels=head_conv_channels,
out_channels=classes,
...
)
)
conv_layers = nn.Sequential(*conv_layers)
bev_decoder
CenterPointDecoder,具体实现流程见下图:

hat/models/task_modules/centerpoint/decoder.py
hat/models/task_modules/fcn/decoder.py
3 浮点模型训练
3.1 Before Start
3.1.1 发布物及环境部署
step2:解压发布包
解压后文件结构如下:
step3:拉取docker环境
3.1.2 数据集准备
3.1.2.1 数据集下载
Full dataset(v1.0)包含多个子数据集,如果不需要进行v1.0-trainval数据集的浮点训练和精度验证,可以只下载v1.0-mini数据集进行小场景的训练和验证。
将下载完成的v1.0-trainval01_blobs.tar~v1.0-trainval10_blobs.tar、v1.0-trainval_meta.tar和can_bus.zip进行解压,解压后的目录如下所示:
3.1.2.2 数据集打包
--src-data-dir为解压后的nuscenes数据集目录;
--target-data-dir为打包后数据集的存储目录;
--version 选项为["v1.0-trainval", "v1.0-test", "v1.0-mini"],如果进行全量训练和验证设置为v1.0-trainval,如果仅想了解模型的训练和验证过程,则可以使用v1.0-mini数据集;v1.0-test数据集仅为测试场景,未提供注释。
全量的nuscenes数据集较大,打包时间较长。每打包完100张会在终端有打印提示,其中train打包约28100张,val打包约6000张。
2.1.2.3 meta文件夹构建
3.1.3 config配置
在进行模型训练和验证之前,需要对configs文件中的部分参数进行配置,一般情况下,我们需要配置以下参数:
device_ids、batch_size_per_gpu:根据实际硬件配置进行device_ids和每个gpu的batchsize的配置;
ckpt_dir:浮点、calib、量化训练的权重路径配置,权重下载链接在config文件夹下的README中;
data_rootdir:2.1.2.2中打包的数据集路径配置;
meta_rootdir :2.1.2.3中创建的meta文件夹的路径配置;
float_trainer下的checkpoint_path:浮点训练时backbone的预训练权重所在路径,可以使用README的# Backbone Pretrained ckpt中ckpt download提供的float-checkpoint-best.pth.tar权重文件。
3.2 浮点模型训练
config文件中的参数配置完成后,使用以下命令训练浮点模型:
float训练后模型ckpt的保存路径为config配置的ckpt_callback中save_dir的值,默认为ckpt_dir。
3.3 浮点模型精度验证
浮点模型训练完成以后,通过指定训好的float_checkpoint_path,使用以下命令验证已经训练好的模型精度:
验证完成后,会在终端打印浮点模型在验证集上检测和分割精度,如下所示:
4 模型量化和编译
4.1 Calibration
模型改造完成并完成浮点训练后,便可进行 Calibration。此过程通过在模型中插入 Observer 的方式,在 forward 过程中统计各处的数据分布情况,从而计算出合理的量化参数。和浮点训练的方式一样,将checkpoint_path指定为训好的浮点权重路径。 通过运行下面的脚本就可以开启模型的Calibration过程:
4.2 Calibration 模型精度验证
calibration完成以后,可以使用以下命令验证经过calib后模型的精度:
对于LSS模型,仅需做calib 即可满足量化精度,无需做qat训练!
4.3 量化模型精度验证
指定calibration-checkpoint后,通过运行以下命令进行量化模型的精度验证:
验证完成后,会在终端输出int模型在验证集上检测和分割精度,格式见3.3。
4.4 仿真上板精度验证
除了上述模型验证之外,我们还提供和上板完全一致的精度验证方法,可以通过下面的方式完成:
4.5 量化模型编译
--opt为优化等级,取值范围为0~3,数字越大优化等级越高,编译时间也会越长;
可以指定--out_dir为编译后产出物的存放路径,默认在ckpt_dir的compile文件夹下
运行后,ckpt_dir的compile目录下会产出以下文件:
5 其他工具
5.1 结果可视化
如果你希望可以看到训练出来的模型单帧的检测效果,我们的tools文件夹下面同样提供了预测及可视化的脚本,你只需要运行以下脚本即可:
注:由于开发机配置不同,plt.show可能不会正常显像,可以在hat/visualize/nuscenes.py添加plt.savefig将结果保存。
可视化示例:

6 板端部署
6.1 上板性能实测
6.2 AIBenchmark 示例
可在板端使用以下命令执行做模型评测:


