1.簡(jiǎn)介
3D Occupancy Networks 的基本思路是將三維空間劃分成體素網(wǎng)格,并對(duì)每個(gè)網(wǎng)格進(jìn)行各類(lèi)感知任務(wù)的預(yù)測(cè)。目前以網(wǎng)格為中心的方法能夠預(yù)測(cè)每個(gè)網(wǎng)格單元的占用率、語(yǔ)義類(lèi)別、未來(lái)運(yùn)動(dòng)位移和實(shí)例信息。3D occupancy 可以對(duì)道路障礙物進(jìn)行更細(xì)粒度的劃分,同時(shí)獲取更精確的占用和語(yǔ)義信息。然而,三維體素表示的處理帶來(lái)了巨大的內(nèi)存和計(jì)算開(kāi)銷(xiāo),導(dǎo)致當(dāng)前占用率預(yù)測(cè)方法的部署受到限制。FlashOcc 作為即插即用的占用網(wǎng)絡(luò),在保持精度的同時(shí)實(shí)現(xiàn)了更快的推理速度和更低的內(nèi)存消耗。本文將介紹 FlashOcc 在地平線(xiàn)征程 6E/M 平臺(tái)上的優(yōu)化部署。
2.性能精度指標(biāo)
3.公版模型介紹
FlashOcc 在該領(lǐng)域做出了開(kāi)創(chuàng)性的貢獻(xiàn),成功地以驚人的精度實(shí)現(xiàn)了實(shí)時(shí) surround 視圖 3D 占用預(yù)測(cè)。此外,在不同的車(chē)載平臺(tái)上部署時(shí)表現(xiàn)出更強(qiáng)的通用性,因?yàn)樗藢?duì)昂貴的體素級(jí)特征處理的需要,其中避免了視圖變換器或 3D(可變形)卷積算子。如下圖所示,F(xiàn)lashOcc 的輸入為 6 張圖像(前后視角+周視),輸出是密集占用預(yù)測(cè)結(jié)果。
FlashOcc 網(wǎng)絡(luò)主要由 5 個(gè)部分組成:
2D 圖像編碼器:使用 ResNet50+FPN 從多視角圖像中提取多尺度圖像特征;
視圖轉(zhuǎn)換模塊:使用 LSS 實(shí)現(xiàn)從 2D 感知視圖圖像特征到 3D BEV 表示的映射;
BEV 編碼器:提取 BEV 空間的特征,并結(jié)合了多尺度的 BEV 特征來(lái)提升特征表示質(zhì)量;
占用預(yù)測(cè)模塊:由多層 Conv 或者復(fù)雜的多尺度特征融合模塊組成,該模塊預(yù)測(cè)每個(gè)體素的分割標(biāo)簽;
可選的時(shí)間融合模塊:由時(shí)空對(duì)齊模塊和特征融合模塊組成,增強(qiáng)對(duì)動(dòng)態(tài)目標(biāo)或?qū)傩缘母兄?/p>
4.地平線(xiàn)部署優(yōu)化
改動(dòng)點(diǎn)說(shuō)明:
輸入圖像大小:由公版的 256x704 調(diào)整為 512x960;
BEV 網(wǎng)格大?。?/strong>由公版的 200x200 調(diào)整為 128x128;
Image encoder backbone:使用地平線(xiàn)深度優(yōu)化的高效 backbone HENet 替換公版中的 ResNet50;
Bev encoder backbone:使用地平線(xiàn)深度優(yōu)化的高效 backbone HENet 替換公版模型中的 CustomResNet;
視圖轉(zhuǎn)換模塊:使用地平線(xiàn)針對(duì)性?xún)?yōu)化后的 LSSTransformer 來(lái)替換公版中的 bevpooling 實(shí)現(xiàn)的 LSSViewTransformer,且移除了公版中的時(shí)序融合模塊;
4.1 性能優(yōu)化4.1.1 Backbone
Image Encoder 采用了 HENet+FPN 來(lái)提取 6V 圖像的多尺度特征,不僅在精度上可與 ResNet50 相媲美,而且在性能上有顯著優(yōu)勢(shì),這里的 FPN 采用的是地平線(xiàn)的高效實(shí)現(xiàn),相對(duì)于公版更加高效。BEV Encoder 同樣采用了 HENet+BiFPN 來(lái)提取 BEV 特征,BiFPN 這種重復(fù)雙向跨尺度連接的結(jié)構(gòu),可以更好地實(shí)現(xiàn)梯度傳播,從而實(shí)現(xiàn) BEV 特征的多尺度融合。
HENet 是針對(duì) J6 平臺(tái)專(zhuān)門(mén)設(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é)可以參考 HENet 高效模型相關(guān)介紹。
代碼路徑:/usr/local/lib/python3.10/dist-packages/hat/models/backbones/henet.py
4.1.2View transformer
View transformer 采用地平線(xiàn)深度優(yōu)化后的 LSSTransformer,替換 J6 平臺(tái)暫不支持的 bevpooling,從而高效地將圖像特征轉(zhuǎn)換到 BEV 空間。為了進(jìn)一步提升性能,將 bev grid size 由公版的 200x200 調(diào)整為了 128x128。LSSTransformer 主要的工作流程如下所示:
View transformer 主要包括分為 3 個(gè)部分:
生成深度特征
對(duì)深度特征和圖像特征做 bev 坐標(biāo)轉(zhuǎn)換
生成視錐點(diǎn)云特征(frustum features)
接下來(lái)將對(duì)這三個(gè)部分的具體代碼實(shí)現(xiàn)進(jìn)行介紹:
生成深度特征View transformer 是基于圖像特征,經(jīng)過(guò)卷積層生成了 depth 為 45 的 depth_feature,并使用 softmax 計(jì)算 depth_feature 的 score 值。對(duì)應(yīng)代碼如下所示:
self.depth_net = ConvModule2d(
in_channels=in_channels,
out_channels=depth,
kernel_size=1,
padding=0,
stride=1,
bias=False,
)
depth = self.softmax(self.depth_net(feats))
代碼路徑:/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/view_fusicon/view_transformer.py
生成 BEV 特征為了減少計(jì)算量,LSSTransformer 首先將圖像特征和深度特征分別轉(zhuǎn)換到 BEV 視角下,然后對(duì)二者進(jìn)行點(diǎn)乘計(jì)算。其中,圖像特征轉(zhuǎn)換到 BEV 空間的采樣坐標(biāo) points 的生成在_gen_reference_point函數(shù)中,計(jì)算邏輯如下:
生成視錐點(diǎn)云特征為了不遺失坐落在相同 voxel 中的點(diǎn)云特征,將對(duì)每個(gè) voxel 都采樣 10 次,最終將每個(gè)點(diǎn)云特征相加得到 BEV 特征圖。對(duì)應(yīng)代碼:
class LSSTransformer(ViewTransformer):
...
def _spatial_transfom(self, feats, points):
...
for i in range(self.num_points):
#將圖像特征轉(zhuǎn)換到 BEV 視角下
homo_feat = self.grid_sample(
feat,#[1, 64, 96, 30]
fpoints[i * B : (i + 1) * B],)
#將深度特征轉(zhuǎn)換到 BEV 視角下
homo_dfeat = self.dgrid_sample(
dfeat,#[1, 1, 270, 480]
dpoints[i * B : (i + 1) * B],
)
#生成視錐點(diǎn)云特征
homo_feat = self.floatFs.mul(homo_feat, homo_dfeat)#[1, 64, 128, 128]
homo_feats.append(homo_feat)
trans_feat = homo_feats[0]
for f in homo_feats[1:]:
trans_feat = self.floatFs.add(trans_feat, f)
return trans_feat #[1, 64, 128, 128]
4.2 精度優(yōu)化
FlashOcc 采用以下策略提升浮點(diǎn)精度:
模型結(jié)構(gòu)優(yōu)化:使用更多地平線(xiàn)進(jìn)行針對(duì)性?xún)?yōu)化后的結(jié)構(gòu),包括 backbone、view_transformer、bevencoder 等,浮點(diǎn)精度相對(duì)于公版有所提升;
加載預(yù)訓(xùn)練權(quán)重:加載 HENet 的浮點(diǎn)預(yù)訓(xùn)練權(quán)重。
總結(jié)與建議
5.1 訓(xùn)練建議
浮點(diǎn)訓(xùn)練時(shí)加載 HENet 的預(yù)訓(xùn)練權(quán)重;
5.2 部署建議
選擇合適的 BEV Grid 尺寸從圖像空間到 BEV 空間的轉(zhuǎn)換,是稠密特征到稠密特征的重新排列組合,計(jì)算量比較大,與圖像尺寸以及 BEV 特征圖尺寸成正相關(guān)。若要保持 BEV Grid 的分辨率不變(比如 0.5m/格),則需要大大增加 BEV 特征圖的尺寸,從而使得端上計(jì)算負(fù)擔(dān)和帶寬負(fù)擔(dān)都過(guò)重;若保持 BEV 特征圖的尺寸不變,則需要使用更粗粒度的 BEV Grid,感知精度就會(huì)下降(每個(gè) grid 的尺寸增加)。所以在模型設(shè)計(jì)之初,綜合考慮模型的精度和性能以選擇合適的 BEV Grid 尺寸。
使用高效 backbone 提取特征建議選擇 J6 平臺(tái)高效 Backbone 來(lái)搭建模型,高效 Backbone 經(jīng)過(guò)在 J6 平臺(tái)的迭代優(yōu)化和驗(yàn)證,相比其它公版 Backbone,在性能和精度上可以取得更加出色的效果,因此選取 J6 平臺(tái)高效 Backbone 來(lái)搭建模型可以對(duì)整個(gè)場(chǎng)景模型帶來(lái)性能和精度的增益。
附錄
論文:FlashOcc
公版模型代碼:Github-FlashOcc