地平線 LiDAR-Camera 融合多任務(wù) BEVFusion 參考算法-V1.0
1.簡(jiǎn)介
2.性能精度指標(biāo)
模型參數(shù):
模型數(shù)據(jù)集Input shapeLiDAR StreamCamera StreamBEV HeadOcc Head
BEVFusion | Nuscenes | 圖像輸入:6x3x512x960點(diǎn)云輸入:1x5x20x40000 | CenterPoint | BEVFormer | BEVFormerDetDecoder | BevformerOccDetDecoder |
性能精度表現(xiàn):
浮點(diǎn)**精度** NDS量化精度 NDSJ6E
Latency/ms | FPS | ||
0.6428 | 0.6352 | 135.64 | 30.95 |
3.公版模型介紹
BEVFusion 主要由相機(jī)流、激光雷達(dá)流、動(dòng)態(tài)融合模塊和檢測(cè)頭組成,下面將逐一進(jìn)行介紹。
3.1 相機(jī)流
相機(jī)流將多視角圖像轉(zhuǎn)到 BEV 空間,由圖像編碼器、視覺(jué)投影模塊、BEV 編碼器組成。
3.1.1 圖像**編碼器**
圖像編碼器旨在將輸入圖像編碼為語(yǔ)義信息豐富的深度特征,它由用于基本特征提取的 2D backbone Dual-Swin-Tiny 和用于多尺度特征提取的 FPN 組成,并采用了一個(gè)簡(jiǎn)單的功能自適應(yīng)模塊 ADP 來(lái)完善上采樣功能,如下圖所示:
3.1.2 視覺(jué)投影模塊
視覺(jué)投影模塊采用 LSS 將圖像特征轉(zhuǎn)換為 3D 自車坐標(biāo),將圖像視圖作為輸入,并通過(guò)分類方式密集地預(yù)測(cè)深度。
然后,根據(jù)相機(jī)外參和預(yù)測(cè)的圖像深度,獲取偽體素。
3.1.3 BEV 編碼模塊
BEV 編碼模塊采用空間到通道(S2C)操作將 4D 偽體素特征編碼到 3D BEV 空間,從而保留語(yǔ)義信息并降低成本。然后又使用四個(gè) 3 × 3 卷積層縮小通道維度,并提取高級(jí)語(yǔ)義信息。
3.2 LiDAR 流
LiDAR 流將激光雷達(dá)點(diǎn)轉(zhuǎn)換為 BEV 空間,BEVFusion 采用 3 種流行的方法,PointPillars、CenterPoint 和 TransFusion 作為激光雷達(dá)流,從而展示模型框架的優(yōu)秀泛化能力。
3.3 動(dòng)態(tài)融合模塊
動(dòng)態(tài)融合模塊的作用是將 concat 后的相機(jī)、 LiDAR 的 BEV 特進(jìn)行有效融合。受 的啟發(fā), BEVFusion 應(yīng)用一個(gè)簡(jiǎn)單的通道注意力模塊來(lái)選擇重要的融合特征,網(wǎng)絡(luò)結(jié)構(gòu)圖如下所示:
4.地平線部署優(yōu)化
地平線參考算法使用流程請(qǐng)參考附錄《TCJ6007-J6 參考算法使用指南》;對(duì)應(yīng)高效模型設(shè)計(jì)建議請(qǐng)參考附錄《J6 算法平臺(tái)模型設(shè)計(jì)建議
4.1 優(yōu)化點(diǎn)總結(jié)
整體情況:
BEVFusion 參考算法采用 BEVFormer 和 centerpoint 分別生成視覺(jué)和 LiDAR BEV 特征,然后使用 SE 模型融合 BEV 特征,最后將 BEV 特征解碼。
暫時(shí)無(wú)法在飛書(shū)文檔外展示此內(nèi)容
改動(dòng)點(diǎn):
相機(jī)流使用了地平線深度優(yōu)化后的 bevformer 參考算法,并將其轉(zhuǎn)換到 LiDAR 坐標(biāo)系,其相對(duì)于公版的優(yōu)化如下:
使用地平線深度優(yōu)化后的高效 backbone HENet 提取圖像特征;
將 attention 層的 mean 替換為 conv 計(jì)算,使性能上獲得提升;
公版模型中,在 Encoder 的空間融合模塊,會(huì)根據(jù) bev_mask 計(jì)算有效的 query 和 reference_points,輸出 queries_rebatch 和 reference_points_rebatch,作用為減少交互的數(shù)據(jù)量,提升模型運(yùn)行性能。對(duì)于稀疏的 query 做 crossattn 后再將 query 放回到 bev_feature 中。;
修復(fù)了公版模型中時(shí)序融合的 bug,并獲得了精度上的提升,同時(shí)通過(guò)對(duì)關(guān)鍵層做 int16 的量化精度配置以保障 1%以內(nèi)的量化精度損失。
LiDAR 流采用了地平線深度優(yōu)化后的 centerpoint 參考算法,其相對(duì)于公版的優(yōu)化如下:
前處理部分的輸入為 5 維點(diǎn)云并做歸一化處理,對(duì)量化訓(xùn)練更加友好;
PillarFeatutreNet 中的 PFNLayer 使用 Conv2d + BatchNorm2d + ReLU,替換原有的 Linear + BatchNorm1d + ReLU,使該結(jié)構(gòu)可在 BPU 上高效支持,實(shí)現(xiàn)了性能提升;
PillarFeatutreNet 中的 PFNLayer 使用 MaxPool2d,替換公版的 torch.max,便于性能的提升;
Scatter 過(guò)程使用 horizon_plugin_pytorch 優(yōu)化實(shí)現(xiàn)的 point_pillars_scatter,便于模型推理優(yōu)化,邏輯與 torch 公版相同;
對(duì)于耗時(shí)嚴(yán)重的 OP,采用 H、W 維度轉(zhuǎn)換的方式,將較大維數(shù)放到 W 維度,比如 1x5x40000x20 轉(zhuǎn)換為 1x5x20x40000;
相對(duì)于公版,增加了 OCC 任務(wù)頭,實(shí)現(xiàn)了 LiDAR+Camera+OCC 動(dòng)靜態(tài)二網(wǎng)合一;
4.2 性能優(yōu)化4.2.1 相機(jī)流
公版 BEVFusion 使用流行的 Lift-Splat-Shoot(LSS)并適度調(diào)整以提高性能。參考算法直接采用了地平線深度優(yōu)化后的 BEVFormer 參考算法作為相機(jī)流網(wǎng)絡(luò),bev 網(wǎng)格的尺寸配置為 128 x128。
改動(dòng)點(diǎn) 1:
backbone 由公版的 Dual-Swin-Tiny 替換為地平線的高效 backbone HENet,不僅在精度上可與 ResNet50 相媲美,而且在性能上有顯著優(yōu)勢(shì)。
HENet 是針對(duì) 征程 6 平臺(tái)專門設(shè)計(jì)的高效 backbone,其采用了純 CNN 架構(gòu),總體可分為四個(gè) stage,每個(gè) stage 會(huì)進(jìn)行 2 倍下采樣。以下為總體的結(jié)構(gòu)配置:
depth = [4, 3, 8, 6]
block_cls = ["GroupDWCB", "GroupDWCB", "AltDWCB", "DWCB"]
width = [64, 128, 192, 384]
attention_block_num = [0,0,0,0]
mlp_ratios, mlp_ratio_attn = [2, 2, 2, 3], 2
act_layer = ["nn.GELU", "nn.GELU", "nn.GELU", "nn.GELU""]
use_layer_scale = [True,True,True,True]
final_expand_channel, feature_mix_channel = 0,1024
down_cls = ["S2DDown", "S2DDown", "S2DDown", "None"71
模型相關(guān)細(xì)節(jié)可以參考。
代碼路徑:/usr/local/lib/python3.10/dist-packages/hat/models/backbones/henet.py
改動(dòng)點(diǎn) 2:
bevformer 中的Temporal Self-Attention通過(guò)引入時(shí)序信息與當(dāng)前時(shí)刻的 BEV Query 進(jìn)行融合,提高 BEV Query 的建模能力,Temporal Self-Attention中最關(guān)鍵的結(jié)構(gòu)為MultiScaleDeformableAttention。
經(jīng)評(píng)估,該模塊中的 mean 對(duì)性能影響較大,參考算法中將其替換為固定 weight 的 conv 計(jì)算,從而獲取性能上的提升,相關(guān)代碼:
class HorizonTemporalSelfAttention(MultiScaleDeformableAttentionBase):
"""The basic structure of HorizonTemporalSelfAttention.
Args:
embed_dims: The embedding dimension of Attention.
num_heads: Parallel attention heads.
num_levels: The num of featuremap.
num_points: The num points for each head sample.
grid_align_num: The align num for grid, align the grid shape of \
gridsample operator to \
[bs * numhead, -1, grid_align_num * numpoints, 2].
num_bev_queue: The num queue for temporal fusion.
reduce_align_num: The align num for reduce mean, align the shape to \
[bs, num_bev_queue * reduce_align_num, -1, num_query].
dropout: Probability of an element to be zeroed.
feats_size: The Size of featmaps.
"""
def
__init__
(
self,
embed_dims: int = 256,
num_heads: int = 8,
num_levels: int = 4,
num_points: int = 4,
grid_align_num: int = 8,
num_bev_queue: int = 2,
reduce_align_num: int = 1,
dropout: float = 0.1,
feats_size: Sequence[Sequence[int]] = ((128, 128),),
) -> None:
super().
__init__
(
embed_dims=embed_dims,
num_heads=num_heads,
num_levels=num_levels,
num_points=num_points,
grid_align_num=grid_align_num,
feats_size=feats_size,
)
self.dropout = nn.Dropout(dropout)
self.num_bev_queue = num_bev_queue
self.reduce_align_num = reduce_align_num
...
#將mean計(jì)算替換為conv計(jì)算
self.query_reduce_mean = nn.Conv2d(
self.num_bev_queue * self.reduce_align_num,
self.reduce_align_num,
1,
bias=False,
)
代碼路徑:/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/bevformer/attention.py
改動(dòng)點(diǎn) 3:
Spatial Cross-Attention利用 Temporal Self-Attention 模塊輸出的 bev_query, 對(duì)主干網(wǎng)絡(luò)和 Neck 網(wǎng)絡(luò)提取到的多尺度環(huán)視圖像特征進(jìn)行查詢,生成 BEV 空間下的BEV Embedding特征。公版的 BEVFormer 中采用 bevmask 來(lái)減少 camera 的 query 點(diǎn)數(shù)的優(yōu)化,但是由于涉及到 BPU 不支持的動(dòng)態(tài) shape,并且涉及到運(yùn)行效率較低的 gather/scatter 操作(當(dāng)前 gather 算子已經(jīng)支持 BPU 加速)。進(jìn)一步分析發(fā)現(xiàn):
從 bev voxel 的角度來(lái)看,中心點(diǎn)到 multi camera 的映射是稀疏的;
從 bev pillar 的角度來(lái)看,通常每個(gè) pillar 只會(huì)映射到 1-2 個(gè) camera;
基于以上分析以及實(shí)驗(yàn)結(jié)果,參考算法在設(shè)置了virtual_bev_h、virtual_bev_w、max_numcam_overlap這 3 個(gè)參數(shù)對(duì)稀疏率進(jìn)行配置,這 3 個(gè)參數(shù)的具體含義是:
virtual_bev_h:虛擬 bev 的高度,用于計(jì)算將稀疏點(diǎn)集恢復(fù)為密集 bev 的網(wǎng)格,參考算法中配置為 64;
virtual_bev_w:虛擬 bev 的寬度,用于計(jì)算將稀疏點(diǎn)集恢復(fù)為密集 bev 的網(wǎng)格,參考算法中配置為 80;
max_numcam_overlap:每個(gè) bev pillar 映射到的最多 camera 數(shù)量,參考算法中配置為 2;
view_transformer=dict(
type="SingleBevFormerViewTransformer",
bev_h=bev_h_,
bev_w=bev_w_,
pc_range=point_cloud_range,
num_points_in_pillar=2,
embed_dims=
_dim_
,
queue_length=1,
in_indices=(-1,),
single_bev=True,
use_lidar2img=use_lidar2img,
max_camoverlap_num=max_camoverlap_num, #2
virtual_bev_h=64,
virtual_bev_w=80,
positional_encoding=dict(
type="LearnedPositionalEncoding",
num_feats=
_pos_dim_
,
row_num_embed=bev_h_,
col_num_embed=bev_w_,
),
代碼路徑:samples/ai_toolchain/horizon_model_train_sample/scripts/configs/lidar_bevfusion/bevfusion_pointpillar_henet_multisensor_multitask_nuscenes.py
4.2.2 LiDAR 流
公版 BEVFusion 采用了當(dāng)前流行的 3 種激光點(diǎn)云檢測(cè)模型 PointPillars , CenterPoint 和 TransFusion 作為 LiDAR 流來(lái)展示框架的通用性。BEVFusion 參考算法復(fù)用了經(jīng)過(guò)深度優(yōu)化的 centerpoint 參考算法,其相對(duì)于公版主要做了以下性能優(yōu)化,下面將逐一介紹。
改動(dòng)點(diǎn) 1:
為了應(yīng)用 2D 卷積架構(gòu),PillarFeatutreNet 將點(diǎn)云(P,N,5)轉(zhuǎn)換為 2D 偽圖像,整體步驟如下圖所示:
公版模型中 PillarFeatutreNet 中的部分算子在 BPU 運(yùn)行效率比較低,所以參考算法對(duì)其做了替換:
PillarFeatutreNet 中的 PFNLayer 使用 BPU 上運(yùn)行比較高效的 Conv2d + BathNorm2d + ReLU 算子,替換了公版的 Linear + BatchNorm1d + ReLU 結(jié)構(gòu),實(shí)現(xiàn)了性能的提升;
PillarFeatutreNet 中的 PFNLayer 使用 MaxPool2d,替換原有的 torch.max,便于性能的提升,對(duì)應(yīng)代碼:
class PFNLayer(nn.Module):
def
__init__
(
self,
in_channels: int,
out_channels: int,
bn_kwargs: dict = None,
last_layer: bool = False,
use_conv: bool = True,
pool_size: Tuple[int, int] = (1, 1),
hw_reverse: bool = False,
):
"""Pillar Feature Net Layer.
This layer is used to convert point cloud into pseudo-image.
Can stack multiple to form Pillar Feature Net.
The original PointPillars paper uses only a single PFNLayer.
Args:
in_channels (int): number of input channels.
out_channels (int): number of output channels.
bn_kwrags (dict): batch normalization arguments. Defaults to None.
last_layer (bool, optional): if True, there is no concatenation of
layers. Defaults to False.
"""
...
if not self.use_conv:
...
else:
#使用Conv2d + BathNorm2d + ReLU,
#替換了公版的 Linear + BatchNorm1d + ReLU
self.linear = nn.Conv2d(
in_channels, self.units, kernel_size=1, bias=False
)
self.norm = nn.BatchNorm2d(self.units, **bn_kwargs)
self.relu = nn.ReLU(inplace=True)
#使用 MaxPool2d,替換torch.max
self.max_pool = nn.MaxPool2d(
kernel_size=pool_size, stride=pool_size
)
代碼路徑:/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/lidar/pillar_encoder.py
改動(dòng)點(diǎn) 2:
如上圖所示,Scatter 是實(shí)現(xiàn)偽圖像轉(zhuǎn)換的重要一個(gè)步驟,參考算法使用horizon_plugin_pytorch實(shí)現(xiàn)的point_pillars_scatter,便于模型推理優(yōu)化,邏輯與公版相同。對(duì)應(yīng)代碼:
from horizon_plugin_pytorch.nn.functional import point_pillars_scatter
class PointPillarScatter(nn.Module):
...
def forward(
...
):
#input_shape=(coors_range[3:] - coors_range[:3]) / voxel_size
self.nx = input_shape[0]
self.ny = input_shape[1]
if self.use_horizon_pillar_scatter: #對(duì)應(yīng)改動(dòng)4
if len(voxel_features.shape) == 4:
P, C = voxel_features.size(2), voxel_features.size(3)
voxel_features = voxel_features.reshape(P, C)
out_shape = (batch_size, self.nchannels, self.ny, self.nx)
#(P, C)-->(batch,C,H,W)
batch_canvas = point_pillars_scatter(
voxel_features, coords, out_shape
)
else:
...
return batch_canvas
其中,核心函數(shù)point_pillars_scatter是在horizon_plugin_pytorch中實(shí)現(xiàn)的。
代碼路徑: /usr/local/lib/python3.10/dist-packages/hat/models/task_modules/lidar/pillar_encoder.py
4.2.3 動(dòng)態(tài)融合模塊
相對(duì)于公版的動(dòng)態(tài)融合模塊(參考 3.3 節(jié)),參考算法在 concat 后新增了 1 個(gè) conv1x1,有助于性能的提升,相關(guān)代碼如下:
class BevFuseModule(nn.Module):
"""BevFuseModule fuses features using convolutions and SE block.
Args:
input_c: The number of input channels.
fuse_c: The number of channels after fusion.
"""
def
__init__
(self, input_c: int, fuse_c: int):
super().
__init__
()
self.reduce_conv = ConvModule2d(
input_c,
fuse_c,
kernel_size=1,
stride=1,
padding=0,
norm_layer=nn.BatchNorm2d(fuse_c, eps=1e-3, momentum=0.01),
act_layer=nn.ReLU(inplace=False),
...
def forward(self, x: torch.Tensor):
#增加了 conv1x1
x = self.reduce_conv(x)
x = self.conv2(x)
pts_feats = self.seblock(x)
return pts_feats
代碼路徑: /usr/local/lib/python3.10/dist-packages/hat/models/task_modules/lidar_fusion/fusion_module.py
4.3 浮點(diǎn)精度優(yōu)化4.3.1 旋轉(zhuǎn)增強(qiáng)
在模型訓(xùn)練時(shí),參考算法對(duì) bev 進(jìn)行旋轉(zhuǎn)增強(qiáng),相關(guān)代碼如下:
train_dataset = dict(
type="NuscenesBevSequenceDataset",
data_path=os.path.join(data_rootdir, "train_lmdb"),
...
transforms=[
dict(type="MultiViewsImgResize", size=input_size),
dict(type="MultiViewsImgFlip"),
dict(type="MultiViewsImgRotate", rot=(-5.4, 5.4)),
dict(type="BevBBoxRotation", rotation_3d_range=(-0.3925, 0.3925)),
dict(type="MultiViewsPhotoMetricDistortion"),
dict(
type="MultiViewsImgTransformWrapper",
transforms=[
dict(type="PILToTensor"),
dict(type="BgrToYuv444", rgb_input=True),
dict(type="Normalize", mean=128, std=128),
],
),
],
)
代碼路徑:
horizon_model_train_sample/scripts/configs/lidar_bevfusion/bevfusion_pointpillar_henet_multisensor_multitask_nuscenes.py
/usr/local/lib/python3.10/dist-packages/hat/data/transforms/multi_views.py
4.3.2 加載預(yù)訓(xùn)練模型
為了提升浮點(diǎn)模型的精度,浮點(diǎn)訓(xùn)練時(shí)相機(jī)流和 LiDAR 流分別加載了預(yù)訓(xùn)練模型,然后再共同訓(xùn)練,對(duì)應(yīng)代碼如下:
float_trainer = dict( type="distributed_data_parallel_trainer", model=model, data_loader=data_loader, model_convert_pipeline=dict( type="ModelConvertPipeline", converters=[ dict( type="LoadCheckpoint", #加載相機(jī)流的預(yù)訓(xùn)練模型 checkpoint_path=os.path.join( camera_ckpt_dir, "float-checkpoint-last.pth.tar" ), allow_miss=True, ignore_extra=True, verbose=True, ), dict( type="LoadCheckpoint", #加載LiDAR流的預(yù)訓(xùn)練模型 checkpoint_path=os.path.join( lidar_ckpt_dir, "float-checkpoint-last.pth.tar" ), ... ),
代碼路徑:
horizon_model_train_sample/scripts/configs/lidar_bevfusion/bevfusion_pointpillar_henet_multisensor_multitask_nuscenes.py
4.4 量化精度優(yōu)化4.4.1 全 int8+部分算子配置為 int16
BEVFusion 參考算法采用的量化策略為全 int8+部分敏感算子通過(guò) set_qconfig 配置為 int16,其中敏感算子的集中分布在 bevformer 部分,如下為 bevformer 中將MultiScaleDeformableAttention中對(duì)量化敏感的算子和 Tensor 配置為 int16 的示例代碼:
class MultiScaleDeformableAttentionBase(nn.Module): """The basic class for MultiScaleDeformableAttention. Args: embed_dims: The embedding dimension of Attention. num_heads: Parallel attention heads. num_levels: The num of featuremap. num_points: The num points for each head sample. grid_align_num: The align num for grid, align the grid shape of \ gridsample operator to \ [bs * numhead, -1, grid_align_num * numpoints, 2]. feats_size: The Size of featmaps. """ def __init__ ( self, embed_dims: int = 256, num_heads: int = 8, num_levels: int = 4, num_points: int = 4, grid_align_num: int = 8, feats_size: Sequence[Sequence[int]] = ((128, 128),), ) -> None: super(). __init__ () ... def set_qconfig(self) -> None: """Set the quantization configuration.""" from hat.utils import qconfig_manager int16_module = [ self.sampling_offsets, self.quant_shape, self.norm_offset, self.add_offset, self.add1, self.mul1, ] for m in int16_module: m.qconfig = qconfig_manager.get_qconfig( activation_qat_qkwargs={"dtype": qint16}, activation_calibration_qkwargs={ "dtype": qint16, }, activation_calibration_observer="mix", )
代碼路徑:
/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/bevformer/attention.py
4.5 其它優(yōu)化4.5.1 增加 Occ 任務(wù)頭
除了公版 BEVFusion 就存在的 3D 檢測(cè)頭外,參考算法增加了 Occ 任務(wù)頭做占用預(yù)測(cè),和 3D 檢測(cè)頭共用特征部分,從而極大地節(jié)省了計(jì)算資源。Occ 任務(wù)頭復(fù)用了中的 head 進(jìn)行設(shè)計(jì),通過(guò)通道轉(zhuǎn)高度模塊將 BEV 特征沿通道維度執(zhí)行簡(jiǎn)單的重塑操作。相關(guān)代碼如下:
def forward(self, img_feats: Tensor): """Forward mould. Args: img_feats: (B, C, Dy, Dx) Returns: occ_pred:tensor """ occ_pred = self.final_conv(img_feats) if self.use_upsample is True: occ_pred = F.interpolate( occ_pred, size=(200, 200), mode="bilinear", align_corners=False ) # (B, C, Dy, Dx) --> (B, Dx, Dy, C) occ_pred = occ_pred.permute(0, 3, 2, 1) bs, Dx, Dy = occ_pred.shape[:3] if self.use_predicter: #通道轉(zhuǎn)高度操作 # (B, Dx, Dy, C) --> (B, Dx, Dy, 2 *C) --> (B, Dx, Dy, Dz* n_cls) occ_pred = self.predicter(occ_pred) occ_pred = occ_pred.view(bs, Dx, Dy, self.Dz, self.num_classes) return occ_pred
代碼路徑:
/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/flashocc/bev_occ_head.py
Occ label 坐標(biāo)轉(zhuǎn)換
由于 Occ label 是在 ego 坐標(biāo)系中標(biāo)注的,所以需要將其統(tǒng)一到 Lidar 坐標(biāo)系,相關(guān)代碼如下:
class NuscenesBevDataset(NuscenesDataset): ... def __getitem__ (self, item): aug_cfg = None if isinstance(item, dict): idx = item["idx"] aug_cfg = item["aug"] else: idx = item sample = self._decode(self.pack_file, self.samples[idx]) sample = NuscenesSample(sample) data = self.sampler(sample) if aug_cfg: data["scenes_aug"] = aug_cfg if self.transforms is not None: data = self.transforms(data) if self.with_lidar_occ: #將Occ label由ego坐標(biāo)系轉(zhuǎn)到lidar坐標(biāo)系 data["gt_occ_info"] = sample._get_lidar_occ(data["lidar2global"]) return data
代碼路徑:
/usr/local/lib/python3.10/dist-packages/hat/data/datasets/nuscenes_dataset.py
Bev 特征裁剪
bev 的空間范圍為[51.2,51.2],grid 尺寸為 128x128;而 occ 的空間范圍為[40,40],grid 尺寸為 128x128。為了將 bev 空間范圍對(duì)齊到 Occ,occ_head中根據(jù)比例將 128x128 的 bev feature 從中心裁剪出 100x100 的 roi,從而滿足 40/51.2=100/128。相關(guān)代碼如下:
occ_head = dict( type="BevformerOccDetDecoder", use_mask=True, lidar_input=lidar_input, camera_input=camera_input, num_classes=num_classes_occ, #使用RoiResize做bev feature的裁剪 roi_resizer=dict( type="RoiResize", in_strides=[1], roi_resize_cfgs=[ dict( in_stride=1, roi_box=(14, 14, 114, 114), ) ], ),
代碼路徑:
horizon_model_train_sample/scripts/configs/lidar_bevfusion/bevfusion_pointpillar_henet_multisensor_multitask_nuscenes.py
5.總結(jié)與建議5.1 訓(xùn)練建議
建議在浮點(diǎn)訓(xùn)練時(shí)分別加載 Lidar 流和相機(jī)流的預(yù)訓(xùn)練模型,然后再訓(xùn)練整個(gè)網(wǎng)絡(luò);
建議選擇合適的 bev grid size,實(shí)驗(yàn)中發(fā)現(xiàn) bev grid size 配置為 128x128 時(shí)的精度比 50x50 要高;
對(duì)于多任務(wù)模型,建議在量化訓(xùn)練適當(dāng)增加 epoch,即量化訓(xùn)練不一定要嚴(yán)格按照浮點(diǎn)訓(xùn)練的 1/10 epoch 來(lái)訓(xùn)練;
浮點(diǎn)訓(xùn)練時(shí)采用CosineAnnealingLrUpdater策略,量化訓(xùn)練時(shí)采用StepDecayLrUpdater策略,對(duì)于此模型來(lái)說(shuō),采用StepDecayLrUpdater策略對(duì)量化訓(xùn)練精度更友好;
5.2 部署建議
建議在模型架構(gòu)設(shè)計(jì)之初就考慮采用地平線深度優(yōu)化后的 backbone 或者網(wǎng)絡(luò)作為 base model;
在注意力機(jī)制中存在一些 add、sum 等 ElementWise 操作,對(duì)于導(dǎo)致性能瓶頸的可以考慮 conv 替換,對(duì)于造成量化風(fēng)險(xiǎn)的可以根據(jù)敏感度分析結(jié)果合理選擇更高的量化精度,以確保注意力機(jī)制的部署;
建議在選擇 bev size 時(shí)考慮性能影響。征程 6 相比于 征程 5 帶寬增大,但仍需注意 bev size 過(guò)大導(dǎo)致訪存時(shí)間過(guò)長(zhǎng)對(duì)性能的影響,建議考慮實(shí)際部署情況選擇合適的 bev size;
若出現(xiàn)性能問(wèn)題可以通過(guò)優(yōu)化 backbone 或者減少層數(shù)或者點(diǎn)數(shù)的方式來(lái)提升性能,但要注意以上操作可能會(huì)導(dǎo)致精度損失,請(qǐng)優(yōu)先考慮對(duì)點(diǎn)數(shù)的減少等對(duì)精度的影響較小性能收益最高的操作;
附錄
論文:
公版模型代碼:https://github.com/ADLab-AutoDrive/BEVFusion
參考算法使用指南:
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。