地平线 bev_cft_efficientnetb3 参考算法-v1.2.1

01 概述

在自动驾驶感知算法中 BEV 感知成为热点话题,BEV 感知可以弥补 2D 感知的缺陷构建 3D “世界”,更有利于下游任务和特征融合。

地平线集成了基于 bev 的纯视觉算法,目前已支持 ipm-based 、lss-based、 transformer-based(Geometry-guided Kernel Transformer、detr3d、petr) 的多种 bev 视觉转换方法。

本文为 camera calibration free 的 transformer-based 的 BEV 感知算法的介绍和使用说明。

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

02 性能精度指标

模型配置:

性能精度表现:

注:Nuscenes 数据集官方介绍:Nuscenes

03 模型介绍

3.1 模型框架

bev_cft 模型结构图

bev_cft 使用多视图的当前帧的 6 个 RGB 图像作为输入。输出是目标的 3D Box 结果。多视角图像首先使用 2D 主干获取 2D 特征。然后投影到 3D BEV 视角。接着对 BEV feature 编码获取深层 BEV 特征。最后,接上任务特定的 head,输出检测结果。

模型主要包括以下部分:

  • Part1—2D Image Encoder:图像特征提取层。使用 2D 主干网络(efficientnet)和 FastSCNN 输出不同分辨率的特征图。返回最后一层–上采样至 1/128 原图大小层,用于下一步投影至 3D 坐标系中。

  • Part2—View transformer:采用 CFT 方式完成 img 2D 到 BEV 3D 的转换。

  • Part3—Bev transforms:对 BEV 特征做数据增强,仅发生在训练阶段。

  • Part4—3D BEV Encoder:BEV 特征提取层。

  • Part5—BEV Decoder

    使用 DepthwiseSeparableCenterPointHead 进行 3D 目标检测任务,检测的类别为 [“car”,“truck”,“bus”,“barrier”,“bicycle”,“pedestrian”]。

3.2 源码说明

config文件

**configs/bev/bev_cft_efficientnetb3_nuscenes.py** 为该模型的配置文件,定义了模型结构、数据集加载,和整套训练流程,所需参数的说明在算子定义中会给出。

配置文件主要内容包括:

#基础参数配置
task_name = "bev_cft_efficientnetb3_nuscenes"
batch_size_per_gpu = 2
device_ids = [0]
#bev参数配置
resize_shape = (3, 792, 1408)
data_shape = (3, 512, 1408)
grid_size = (64, 64)# 模型结构定义
model = dict(type="ViewFusion",backbone=dict(type="efficientnet",model_type="b3",...),neck=dict(type="BiFPN",...),view_transformer=dict(type="CFTTransformer", #cft transform...),bev_transforms=[...],bev_encoder=dict(type="BevEncoder",...),bev_decoders=[dict(type="BevDetDecoder",...)],
)deploy_model = dict(
...
)
...
# 数据加载 
data_loader = dict(type=torch.utils.data.DataLoader,...
)val_data_loader = dict(...)#不同step的训练策略配置
float_trainer=dict(...)
calibration_trainer=dict(...)
qat_trainer=dict(...)
int_infer_trainer=dict(...)
#不同step的验证
float_predictor=dict(...)
calibration_predictor=dict(...)
qat_predictor=dict(...)
int_infer_predictor=dict(...)
#编译配置
compile_cfg = dict(march=march,...
)

注:如果需要复现精度,config 中的训练策略最好不要修改。否则可能会有意外的训练情况出现。

img_encoder

来自 6 个 view 的 image 作为输入通过共享的 backbone(efficientnet-b3)和 neck(BiFPN)输出经过 encoder 后的 feature,feature_shape 为(6*B,C,1/128H,1/128W)。

encoder 即对多个 view 的 img_feature 做特征提取,过程见下图:

对应代码:hat/models/backbones/efficientnet.py hat/models/necks/bifpn.py

view_transformer

view_transformer 采用 CFT(camera free transformer)映射的方法,把图像视角的 img_features 转换到 bev_features。

BEV_shape 为[H’,W’]为[64,64],其转换过程见下图:

cft 框架图

view_transformer 对应代码:

hat/models/task_modules/view_fusion/cft_transformer.pyCFTTransformer

class CFTTransformer(ViewTransformer):...def forward(self, feats: Tensor, data: Tensor,...):query_pos, key_pos, ref_h_embed, ref_h = self._position_embed(feats)bs = feats.shape[0] // self.num_viewskey_pos = key_pos.repeat(bs, 1, 1, 1)tgt = (self.query_embed.weight.view(self.grid_size[0], self.grid_size[1], -1).repeat(bs, 1, 1, 1).permute(0, 3, 1, 2).contiguous())key_pos = self.key_pos_quant(key_pos)feats = self.encoder(feats, pos=key_pos)tgt = self.tgt_quant(tgt)query_pos = self.query_pos_quant(query_pos)ref_h_embed = self.ref_h_quant(ref_h_embed)feats = self.decoder(feats,tgt=tgt,query_pos=query_pos,key_pos=key_pos,ref_h_embed=ref_h_embed,)return feats, ref_h

根据框架图,在 view_transformer 流程中可以分为两部分:

  • position-Aware Enhancement:对位置编码进行强化,对 BEV 2D 和 content 编码,并通过 PA 网络实现特征增强
  • view-Aware Attention:对图像融合坐标位置编码,增强特征
position-Aware Enhancement

Step 1 : postition_embedding

该部分为 BEV 2D 坐标的编码,编码为可学习、参数可更新的PositionEmbeddingLearned2D

class PositionEmbeddingLearned2D(nn.Module):...def forward(self, patch: Tensor) -> Tensor:"""Forward pass of the PositionEmbeddingLearned2D module.Args:patch: Input tensor.Returns:pos: Output tensor."""hw, _ = patch.shapehw = torch.tensor(hw)h = w = torch.sqrt(hw).int()i = torch.arange(h, device=patch.device)j = torch.arange(w, device=patch.device)x_emb = self. col_embed(i)y_emb = self.row_embed(j)pos = x_emb.unsqueeze(1).repeat(1, w, 1) + y_emb.unsqueeze(0).repeat(h, 1, 1)return pos.permute(2, 0, 1).contiguous().unsqueeze(0)

Step 2 : reference height embedding

该步骤为对高度 reference height 的编码。根据位置编码 query_pos 来做高度的预测 ref_h ,然后对高度 ref_h 做正弦函数编码。计算公式为:

对应代码为:

def _position_embed(self, feats: Tensor) -> Tuple[Tensor, Tensor, Tensor, Tensor]:...        height_range = [self.position_range[2], self.position_range[5]]ref_h = self.ref_h_head(query_pos)ref_h = (ref_h.sigmoid() * (height_range[1] - height_range[0])+ height_range[0])ref_h_embed = gen_sineembed_for_position(ref_h, height_range, self.embed_dims)

ref_h_head 为一个输出 channel 为 1 的 mlp:

self.ref_h_head = MLP(input_channels=embed_dims,output_channels=1,feedforward_channels=embed_dims,)

gen_sineembed_for_position实现在hat/models/task_modules/view_fusion/cft_transformer.py

Step 3:结合 BEV 的 content query,细化目标的 height

为了细化高度,引入 BEV 的 content 来提取目标的高度信息:

BEV 的 content 为预设的 query。num_query 为 bevsize 大小。

num_queries = self.grid_size[0] * self.grid_size[1]
self.query_embed = nn.Embedding(num_queries, self.embed_dims)tgt = (self.query_embed.weight.view(self.grid_size[0], self.grid_size[1], -1).repeat(bs, 1, 1, 1).permute(0, 3, 1, 2).contiguous()
)

Content query 经过 MLP 后与 Ref_h 做 mul,然后与 query_pos 做 add。代码:

class Decoder(nn.Module):...def forward(self,x: Tensor,tgt: Tensor,query_pos: Tensor,key_pos: Tensor,ref_h_embed: Tensor,) -> Tensor:...for i, decoder in enumerate(self.decoders):if i > 0:pos_transformation = self.query_trans_pos(tgt)ref_h_embed = self.mul.mul(ref_h_embed, pos_transformation)ref_h_embed = ref_h_embed + query_postgt = decoder(x,tgt=tgt,query_pos=query_pos,key_pos=key_pos,ref_h_embed=ref_h_embed,)return tgtclass Decoder(nn.Module):    ...    def forward(        self,        x: Tensor,        tgt: Tensor,        query_pos: Tensor,        key_pos: Tensor,        ref_h_embed: Tensor,    ) -> Tensor:        ...        for i, decoder in enumerate(self.decoders):            if i > 0:                pos_transformation = self.query_trans_pos(tgt)                ref_h_embed = self.mul.mul(ref_h_embed, pos_transformation)            ref_h_embed = ref_h_embed + query_pos            tgt = decoder(                x,                tgt=tgt,                query_pos=query_pos,                key_pos=key_pos,                ref_h_embed=ref_h_embed,            )        return tgt
view-Aware Attention

该层对图像做 encoder。融合 position 经过一个 self-attention 模块做特征增强。

class CFTTransformer(ViewTransformer):...def forward(self, feats: Tensor, data: Tensor,...):... query_pos, key_pos, ref_h_embed, ref_h = self._position_embed(feats)bs = feats.shape[0] // self.num_viewskey_pos = key_pos.repeat(bs, 1, 1, 1)...key_pos = self.key_pos_quant(key_pos)         feats = self.encoder(feats, pos=key_pos)...

其中位置编码 key_pos 的方式为:

self.pos_embedding = PositionEmbeddingLearned(num_pos_feats=[100, 100, 56], num_pos=num_pos
)

详细实现见 PositionEmbeddingLearned。

图像的 encoder 操作为:

class Encoderlayer(nn.Module):...    def forward(self, x: Tensor, pos: Tensor) -> Tensor:x = self.norm1(x)q = k = self.pos_add.add(x, pos)tgt, _ = self.self_attns(query=q, key=k, value=x)tgt = self.dropout1_add.add(x, self.dropout1(tgt))tgt2 = self.norm2(tgt)tgt2 = self.ffn(tgt2)tgt2 = self.dropout2_add.add(tgt, self.dropout2(tgt2))return tgt2

在公版中,为了减少计算量和内存消耗,在 Decoder 的自注意力计算中做了分组的 Attention,在做 J5 部署时该部分会用到大量的 slice,IO 操作导致带宽资源紧张,因此,地平线版本未做 part attention。

class Decoder(nn.Module):...def forward(self,x: Tensor,tgt: Tensor,query_pos: Tensor,key_pos: Tensor,ref_h_embed: Tensor,) -> Tensor:for i, decoder in enumerate(self.decoders):if i > 0:pos_transformation = self.query_trans_pos(tgt)ref_h_embed = self.mul.mul(ref_h_embed, pos_transformation)ref_h_embed = ref_h_embed + query_postgt = decoder(x,tgt=tgt,query_pos=query_pos,key_pos=key_pos,ref_h_embed=ref_h_embed,)return tgt

decoder 为 cross-attention 操作,num_layers 为 2:

class Decoderlayer(nn.Module):...def forward(self,feat: Tensor,tgt: Tensor,query_pos: Tensor,key_pos: Tensor,ref_h_embed: Tensor,):n, c, h, w = feat.shapebs = n // self.num_viewsfeat = feat.view(-1, self.num_views, c, h, w)key_pos = key_pos.view(-1, self.num_views, c, h, w)feat = feat.permute(0, 2, 1, 3, 4).contiguous().view(bs, c, -1, w)key_pos = (key_pos.permute(0, 2, 1, 3, 4).contiguous().view(bs, c, -1, w))query = self.Qadd.add(tgt, query_pos)query = self.Qadd2.add(query, ref_h_embed)key = self.Kadd.add(feat, key_pos)tgt2, _ = self.cross_attns(query=query, key=key, value=feat)tgt = self.dropout1_add.add(tgt, self.dropout1(tgt2))tgt = self.norm1(tgt)tgt2 = self.ffn(tgt)tgt = self.dropout2_add.add(tgt, self.dropout2(tgt2))tgt = self.norm2(tgt)return tgt

bev_head

检测为多 task 检测,主要分为:

tasks = [dict(name="bbos",num_class=10,class_names=["car","truck","construction_vehicle","bus","trailer","barrier","motorcycle","bicycle","pedestrian","traffic_cone",],)
]

在 nuscenes 数据集中,目标的类别一共被分为了 6 个大类,网络给每一个类都分配了一个 head,装在 headlist 中,而每个 head 内部都为预测的参数。

bev_det 的 head 为DepthwiseSeparableCenterPointHead

对应代码:hat/models/task_modules/centerpoint/head.py

class DepthwiseSeparableCenterPointHead(CenterPointHead):def _make_conv(self,...):pw_norm_layer = nn.BatchNorm2d(in_channels, **self.bn_kwargs)pw_act_layer = nn.ReLU(inplace=True)return SeparableConvModule2d(in_channels=in_channels,...)def _make_task(self, **kwargs):return DepthwiseSeparableTaskHead(**kwargs)class CenterPointHead(nn.Module):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)def forward(self, feats):rets = []feats = feats[0]feats = self.shared_conv(feats)for task in self.task_heads:rets.append(task(feats))

forward 时,经过共享的 SeparableConv 后,将 feature 再分别传入 task_heads 做 task_pred。

hat/models/task_modules/centerpoint/head.py的 TaskHead 对不同的 task 定义 conv_layers:

class DepthwiseSeparableTaskHead(TaskHead):def _make_conv(self,in_channels,...):return SeparableConvModule2d(in_channels=in_channels,...)class TaskHead(nn.Module):def __init__(...):...    for head in self.heads:classes, num_conv = self.heads[head]...#head_convfor _ in range(num_conv - 1):conv_layers.append(self._make_conv(...))c_in = head_conv_channels#cls_layerconv_layers.append(ConvModule2d(in_channels=head_conv_channels,out_channels=classes,...))conv_layers = nn.Sequential(*conv_layers)def forward(self, x):ret_dict = {}for head in self.heads:ret_dict[head] = self.dequant(self.__getattr__(head)(x))return ret_dict

bev_decoder

在检测任务中使用 CenterPointDecoder,具体实现流程见下图:

对应代码:hat/models/task_modules/centerpoint/decoder.py

04 浮点模型训练

4.1 Before Start

4.1.1 发布物及环境部署***

Step 1:获取发布物

下载 OE 包:

horizon_j5_open_explorer_v$version$.tar.gz,获取方式见地平线开发者社区 OpenExplorer 算法工具链 版本发布

Step 2:解压发布包

tar -xzvf horizon_j5_open_explorer_v$version$.tar.gz

解压后文件结构如下:

|-- bsp
|-- ddk
|   |-- package
|   `-- samples
|       |-- ai_benchmark
|       |-- ai_forward_view_sample
|       |-- ai_toolchain
|       |   |-- ...
|       |   |-- horizon_model_train_sample
|       |   `-- model_zoo
|       |-- model_zoo
|       `-- vdsp_rpc_sample
|-- README-CN
|-- README-EN
|-- resolve_all.sh
`-- run_docker.sh

其中horizon_model_train_sample为参考算法模块,包含以下模块:

|-- horizon_model_train_sample  #参考算法示例
|   |-- plugin_basic  #qat 基础示例
|   `-- scripts  #模型配置文件、运行脚本

Step 3:拉取 docker 环境

docker pull openexplorer/ai_toolchain_ubuntu_20_j5_gpu:v$version$
#启动容器,具体参数可根据实际需求配置
#-v 用于将本地的路径挂载到 docker 路径下
nvidia-docker run -it --shm-size="15g" -v `pwd`:/WORKSPACE openexplorer/ai_toolchain_ubuntu_20_j5_gpu:v$version$

4.1.2 数据集准备***

4.1.2.1 数据集下载

进入nuscenes 官网,根据提示完成账户的注册,下载 Full dataset(v1.0)、CAN bus expansion 和 Map expansion(v1.3)这三个项目下的文件。下载后的压缩文件为:

|-- nuScenes-map-expansion-v1.3.zip
|-- can_bus.zip
|-- v1.0-mini.tar
|-- v1.0-trainval01_blobs.tar
|-- ...
|-- v1.0-trainval10_blobs.tar
`-- v1.0-trainval_meta.tar

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 进行解压,解压后的目录如下所示:

|--nuscenes|-- can_bus #can_bus.zip解压后的目录|-- samples #v1.0-trainvalXX_blobs.tar解压后的目录|   |-- CAM_BACK|   |-- ...|   |-- CAM_FRONT_RIGHT|   |--  ...|   `-- RADAR_FRONT_RIGHT|-- sweeps|   |-- CAM_BACK|   |-- ...|   |-- CAM_FRONT_RIGHT|   |--  ...|   `-- RADAR_FRONT_RIGHT|-- v1.0-trainval #v1.0-trainval_meta.tar解压后的数据|-- attribute.json|    ...`-- visibility.json

4.1.2.2 数据集打包***

进入 horizon_model_train_sample/scripts 目录,使用以下命令将训练数据集和验证数据集打包,格式为 lmdb:

#pack train_Set
python3 tools/datasets/nuscenes_packer.py --src-data-dir /WORKSPACE/nuscenes/ --pack-type lmdb --target-data-dir /WORKSPACE/tmp_data/nuscenes/v1.0-trainval --version v1.0-trainval --split-name train
#pack val_Set
python3 tools/datasets/nuscenes_packer.py --src-data-dir /WORKSPACE/nuscenes/ --pack-type lmdb --target-data-dir /WORKSPACE/tmp_data/nuscenes/v1.0-trainval --version v1.0-trainval --split-name val

–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 张。

数据集打包命令执行完毕后会在target-data-dir下生成train_lmdbval_lmdbtrain_lmdbval_lmdb就是打包之后的训练数据集和验证数据集为 config 中的data_rootdir

|-- tmp_data 
|   |-- nuscenes 
|   |   |-- v1.0-trainval
|   |   |   |-- train_lmdb  #打包后的train数据集
|   |   |   |   |-- data.mdb
|   |   |   |   `-- lock.mdb
|   |   |   `-- val_lmdb   #打包后的val数据集
|   |   |   |   |-- data.mdb
|   |   |   |   `-- lock.mdb

4.1.2.3 meta 文件夹构建

tmp_data/nuscenes 下创建 meta 文件夹,将v1.0-trainval_meta.tar压缩包解压至 meta,得到meta/maps文件夹,再将nuScenes-map-expansion-v1.3.zip压缩包解压至meta/maps文件夹下,解压后的目录结构为:

|-- tmp_data 
|   |-- nuscenes 
|   |   |-- meta
|   |   |   |-- maps        #nuScenes-map-expansion-v1.3.zip解压后的目录
|   |   |   |   |-- 36092f0b03a857c6a3403e25b4b7aab3.png
|   |   |   |   |-- ...
|   |   |   |   |-- 93406b464a165eaba6d9de76ca09f5da.png
|   |   |   |   |-- prediction
|   |   |   |   |-- basemap
|   |   |   |   |-- expansion
|   |   |   |-- v1.0-trainval  #v1.0-trainval_meta.tar解压后的目录
|   |   |       |-- attribute.json
|   |   |           ...
|   |   |       |-- visibility.json
|   |   `-- v1.0-trainval 
|   |   |   |-- train_lmdb  #打包后的train数据集
|   |   |   `-- val_lmdb   #打包后的val数据集

4.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 权重文件。

4.2 浮点模型训练

config 文件中的参数配置完成后,使用以下命令训练浮点模型:

python3 tools/train.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --stage float

float 训练后模型 ckpt 的保存路径为 config 配置的 ckpt_callback 中 save_dir 的值,默认为 ckpt_dir。

4.3 浮点模型精度验证

浮点模型训练完成以后,可以使用以下命令验证已经训练好的浮点模型精度:

python3 tools/predict.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --stage float

验证完成后,会在终端打印浮点模型在验证集上检测精度,如下所示:

Per-class results:
Object Class    AP      ATE     ASE     AOE     AVE     AAE
car     0.458   0.552   0.157   0.188   1.263   0.230
...
2023-12-19 17:47:02,796 INFO [nuscenes_metric.py:349] Node[0] NDS: 0.3280, mAP:0.2481
...
2023-06-06 18:24:10,513 INFO [mean_iou.py:170] Node[0] ~~~~ MeanIOU Summary metrics ~~~~
car_AP: [0.5]:0.1182  [1.0]:0.3794  [2.0]:0.6097  [4.0]:0.7232
...
2023-12-19 17:47:03,046 INFO [metric_updater.py:360] Node[0] Epoch[0] Validation bev_cft_efficientnetb3_nuscenes: NDS[0.3280] 
2023-12-19 17:47:03,058 INFO [logger.py:176] Node[0] ==================================================END PREDICT==================================================
2023-12-19 17:47:03,058 INFO [logger.py:176] Node[0] ==================================================END FLOAT PREDICT==================================================

05 模型量化和编译

完成浮点训练后,还需要进行量化训练和编译,才能将定点模型部署到板端。地平线对该模型的量化采用 horizon_plugin 框架,经过 Calibration+QAT 量化训练后,使用compile的工具将量化模型编译成可以上板运行的hbm文件。

5.1 Calibration

模型完成浮点训练后,便可进行 Calibration。calibration 在 forward 过程中通过统计各处的数据分布情况,从而计算出合理的量化参数。通过运行下面的脚本就可以开启模型的 Calibration 过程:

python3 tools/train.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --stage calibration

5.2 Calibration 模型精度验证

Calibration 完成以后,可以使用以下命令验证经过 calib 后模型的精度:

python3 tools/predict.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --stage calibration

验证完成后,会在终端输出 calib 模型在验证集上检测精度,格式见 2.3。

5.3 量化模型训练

Calibration 完成后,就可以加载 calib 权重开启模型的量化训练。量化训练其实是在浮点训练基础上的 finetue,具体配置信息在 config 的 qat_trainer 中定义。

量化训练的时候,初始学习率设置为浮点训练的十分之一,训练的 epoch 次数也大大减少。和浮点训练的方式一样,将 checkpoint_path 指定为训好的 calibration 权重路径。

通过运行下面的脚本就可以开启模型的 qat 训练:

python3 tools/predict.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --stage qat

5.4 量化模型精度验证

Calibration 完成以后,可以使用以下命令验证经过 calib 后模型的精度:

#qat模型精度验证python3 tools/predict.py --stage qat--config configs/bev/bev_cft_efficientnetb3_nuscenes.py

验证完成后,会在终端输出 calib 模型在验证集上检测精度,格式见 2.3。

5.5 量化模型精度验证

指定 calibration-checkpoint 后,通过运行以下命令进行量化模型的精度验证:

python3 tools/predict.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --stage int_infer

qat 模型的精度验证对象为插入伪量化节点后的模型(float32);quantize 模型的精度验证对象为定点模型(int8),验证的精度是最终的 int8 模型的真正精度,这两个精度应该是十分接近的。

5.6 仿真上板精度验证

除了上述模型验证之外,我们还提供和上板完全一致的精度验证方法,可以通过下面的方式完成:

python3 tools/align_bpu_validation.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py

5.7 量化模型编译

在量化训练完成之后,可以使用compile_perf.py脚本将量化模型编译成可以板端运行的hbm模型,同时该工具也能预估在 BPU 上的运行性能,compile_perf 脚本使用方式如下:

python3 tools/compile_perf.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --out-dir ./ --opt 3

opt 为优化等级,取值范围为 0~3,数字越大优化等级越高,编译时间更长,但部署性能更好。compile_perf 脚本将生成。html 文件和。hbm 文件(compile 文件目录下),。html 文件为 BPU 上的运行性能,。hbm 文件为上板实测文件。

运行后,ckpt_dir 的 compile 目录下会产出以下文件。

|-- compile |   |-- .html #模型在bpu上的静态性能数据 |   |-- .json  |   |-- model.hbm  #板端部署的模型|   |-- model.hbir #编译过程的中间文件​   `-- model.pt   #模型的pt文件

06 其他工具

6.1 结果可视化

如果你希望可以看到训练出来的模型对于单帧的检测效果,我们的 tools 文件夹下面同样提供了预测及可视化的脚本,你只需要运行以下脚本即可:

python3 tools/infer.py --config configs/bev/bev_cft_efficientnetb3_nuscenes.py --save-path ./

可视化结果将会在 save-path 路径下输出。

07 板端部署

7.1 上板性能实测

使用hrt_model_exec perf工具将生成的。hbm 文件上板做 BPU 性能 FPS 实测,hrt_model_exec perf参数如下:

hrt_model_exec perf --model_file {model}.hbm \     --thread_num 8 \--frame_count 2000 \--core_id 0 \--profile_path '.'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/840363.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第八次高级语言程序作业

班级:https://edu.cnblogs.com/campus/fzu/2024C 作业要求: https://edu.cnblogs.com/campus/fzu/2024C/homework/13307 学号:102400110 姓名:阿卜杜拉 阿布力克木 11.13.111.13.211.13.311.13.611.13.712.112.212.312.8 12.9本次作业对我来说难度很高,我会反复观看

js+jquery实现贪吃蛇经典小游戏

项目只使用到了html,css,js,jquery技术点,没有使用游戏框架,下载本地直接双击index.html 运行即可体验游戏效果。项目展示 进入游戏游戏开始游戏暂停html文件 <!DOCTYPE html> <html> <head><meta charset="UTF-8"><meta name="vi…

rebuttal 摘录

link: https://mp.weixin.qq.com/s/m_cYjUZuzKYAAm3bOA8Srg常用句式 以下列举一些 rebuttal 中的常用句式,供大家选择使用: 开头 Thank you for your suggestion. Thank you for the positive/detailed/constructive comments. We sincerely thank all reviewers and ACs for…

题目集4~6的总结Blog

题目一:答题程序设计与实现 功能解析 题目一要求设计一个模拟答题系统,功能包括: 题目管理: 输入题目信息,包括题号、内容和标准答案。 支持删除某些题目,使其无效化。 试卷管理: 输入试卷信息,包括试卷编号、包含的题目及每题分值。 验证试卷总分是否满足预设标准(如…

第九周学习总结

学期2024-2025-1 学号20241414 《计算机基础与程序设计》第九周学习总结 作业信息这个作业属于哪个课程 <班级的链接>2024-2025-1-计算机基础与程序设计这个作业要求在哪里 <作业要求的链接>2024-2025-1计算机基础与程序设计第九周作业这个作业的目标 操作系统责任…

k8s阶段03 持久卷, PV和PVC, CSI存储方案示例csi-driver-nfs, OpenEBS, ConfigMap, Secret, DownwardAPI和Projected

2持久卷 PV和PVC在Pod级别定义存储卷有两个弊端卷对象的生命周期无法独立于Pod而存在用户必须要足够熟悉可用的存储及其详情才能在Pod上配置和使用卷PV和PVC可用于降低这种耦合关系PV(Persistent Volume)是集群级别的资源,负责将存储空间引入到集群中,通常由管理员定义PVC(…

iOS 审核被拒记录 2.5.1

解决方案一(当前项目不需要HealthKit框架,将HealthKit相关内容和权限移除)解决方案二(当前项目需要HealthKit框架)Guideline 2.5.1 - Performance - Software RequirementsYour apps binary includes references to HealthKit components, but the app does not appear to …

20241313 刘鸣宇 《计算机基础与程序设计》第九周学习总结

2024-2025-1 20241313 刘鸣宇 《计算机基础与程序设计》第九周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标 <…

MySQL原理简介—4.深入分析Buffer Pool

大纲 1.Buffer Pool是什么 2.如何配置Buffer Pool的大小 3.数据页是MySQL中抽象出来的数据单位 4.数据页如何对应Buffer Pool中的缓存页 5.缓存页对应的描述信息是什么 6.Buffer Pool简单总结 7.数据库启动时如何初始化Buffer Pool 8.free链表可判断哪些缓存页是空闲的 9.free链…

MySQL原理简介—2.InnoDB架构原理和执行流程

大纲 1.更新语句在MySQL中是如何执行的 2.重要的内存结构—Buffer Pool缓冲池 3.undo日志文件如何让更新的数据可以回滚 4.更新Buffer Pool缓冲池中的缓存数据 5.Redo Log Buffer如何避免宕机时数据丢失 6.如果还没提交事务时MySQL宕机了怎么办 7.提交事务时将redo日志写入磁盘…

【Azure 环境】从网络包中分析出TLS加密套件信息

An TLS 1.2 connection request was received from a remote client application, but non of the cipher suites supported by the client application are supported by the server. The connection request has failed.从远程客户端应用程序收到 TLS 1.2 连接请求,但服务器…